ProgressDialog not shown when AsyncTask.get() called

18,971

Solution 1

Yes, get() waits if necessary for the computation to complete, and then retrieves its result. This means, that you are blocking your UI thread, waiting for the result.

Solution: Don't call get

Usually, you will call a function (callback) in the postExecute.

Solution 2

Calling .get() changes your AsyncTask into an effective "SyncTask" as it causes the current thread (which would be the UI thread) to wait until the AsyncTask has finished its processing. Since you are now blocking the UI thread the call to the ProgressDialog's .show() method never gets a chance to allow the dialog to draw itself the screen.

Removing the call will allow it to run properly in the background.

If you need to do processing after the task has completed I suggest you either put it inside the onPostExecute method itself or use a callback to the Activity from onPostExecute.

Solution 3

If I understand your question correctly, you need to update the progress of your AsyncTask in a ProgressDialog and this isn't currently working. So a couple of things to note: I'm not sure what you're trying to achieve with .get() but I'll assume you want to display the progress.

I've modified your program below to update the UI thread with your AsyncTask's progress. Everytime you need to update the progress, update that prog variable in the doInBackground method.

public class myAsync extends AsyncTask<String, Integer, List> {

  String message; // for dialog message
  ProgressDialog progress; 
  Intent myIntent;
  Context ctx;

  public myAsync(String message, Context ctx) {
    this.message = message;
    this.ctx = ctx;
    progress = new ProgressDialog(ctx);
  }

  @Override
  protected void onPreExecute() { 
    // Runs on the UI thread
    progress.setMessage(message);
    progress.setIndeterminate(true);
    progress.setCancelable(false);
    progress.show();    
  }

  @Override
  protected List doInBackground(String... params) {
    // Runs in the background thread
    // publish your progress here!!
    int prog = 5; // This number will represent your "progress"
    publishProgress(prog);
    return anyList; 
  }


  protected void onProgressUpdate(Integer... progress) {
    // Runs in the UI thread
    // This method will fire (on the UI thread) EVERYTIME publishProgress
    // is called.
    Log.d(TAG, "Progress is: " +progress);
  }

  @Override
  protected void onPostExecute(List result) {
    // Runs in the UI thread

    for (int i=0; i<result.size(); i++) {
      Log.d(TAG, "List item: " + result.get(i));
    }

    if(progress.isShowing())
      progress.dismiss();
  }
}
Share:
18,971

Related videos on Youtube

Ogulcan Orhan
Author by

Ogulcan Orhan

Android &amp; iOS developer.

Updated on June 04, 2022

Comments

  • Ogulcan Orhan
    Ogulcan Orhan almost 2 years

    Possible Duplicate:
    AsyncTask block UI threat and show progressbar with delay

    I want to show a progressDialog while retrieving JSON from any server. So I had used AsyncTask as a solution (not sure any different way out).

    Everything is fine, the ProgressDialog works properly until I call .get() method using AsyncTask instance. I suppose it's blocking UI somehow. Here is my AsyncTask:

    public class myAsync extends AsyncTask<String, String, List> {
    
        String message; // for dialog message
        ProgressDialog progress; 
        Intent myIntent;
        Context ctx;
    
        public myAsync(String message, Context ctx) {
            this.message = message;
            this.ctx = ctx;
            progress = new ProgressDialog(ctx);
        }
    
        @Override
        protected void onPreExecute() { 
            progress.setMessage(message);
            progress.setIndeterminate(true);
            progress.setCancelable(false);
            progress.show();    
        }
    
        @Override
        protected List doInBackground(String... params) {
            //returns any list after the task
            return anyList; 
        }
    
        @Override
        protected void onPostExecute(List result) {
            if(progress.isShowing())
                progress.dismiss();
        }
    }
    

    And here is myActivity which is calls AsyncTask:

    myAsync asyncTask = new myAsync("Loading...", this);
    asyncTask.execute("Any string", "Other string");
    asyncTask.get(); // If I comment out this line, ProgressDialog works
    

    After execute, when I tried to log the result from doInBackground and onPostExecute both there is no problem. But if I want to get with .get() the result ProgressDialog is not shown or shown so little time (maybe 0.2 seconds)

    What's the problem?

  • Jake Wharton
    Jake Wharton over 12 years
    Both onPreExecute and onPostExecute are run on the UI thread. doInBackground is the only thing that is not.
  • James andresakis
    James andresakis over 12 years
    @JakeWharton I think they only return data to the UI thread and do not run on it but I could be wrong.....I dont exactly have the android documentation remembered line for line yet lol
  • rds
    rds over 12 years
    See stackoverflow.com/questions/3291490/… for a sample implementation
  • rds
    rds over 12 years
    With get, he obviously wants to get the result from the task, in order to update his interface
  • Marvin Pinto
    Marvin Pinto over 12 years
    @rds Would you ever use .get in the context of an AsyncTask? Hence why my assumption "I'm not sure what you're trying to achieve with..." and then on to my interpretation of the OP's question.
  • Ogulcan Orhan
    Ogulcan Orhan over 12 years
    @Marvin, firstly thanks for your comment. Simply, I'm getting json from a web server. While doing this transaction, just want to show progressdialog windows, that's all. If I do not call .get(), it's fine. Dialog is shown as soon as clicked the button (button'll trigger async). But by the way I need json result too. As I know .get() method returns the result. When I tried to get, dialog window is shown so little time during the transaction. I hope it's easier now.
  • Ogulcan Orhan
    Ogulcan Orhan over 12 years
    I guess you're right but can you explain it more? Any snippets. Because I'm not sure about how to use callback from onPostExecute. Thanks.
  • Ogulcan Orhan
    Ogulcan Orhan over 12 years
    I already tried this, not worked. Thanks anyway.
  • Marvin Pinto
    Marvin Pinto over 12 years
    @OgulcanOrhan Try out the suggestions the other answerers posted and if you're still stuck, I can try to help you out.
  • Marvin Pinto
    Marvin Pinto over 12 years
    @OgulcanOrhan I've made a minor edit to my answer's onPostExecute method to demonstrate how you would process the items in your list on the UI Thread. So if you have to for example update a ListView, you would do that in the onPostExecute method. This would be what I presume you're trying to do. i.e. After it's done executing, get and do something with your results. Well the do something part is what you want to put in the onPostExecute method.
  • Ogulcan Orhan
    Ogulcan Orhan over 12 years
    Got it! Thanks for sample, solved this but still have problems for different subject.
  • Ogulcan Orhan
    Ogulcan Orhan over 12 years
    @MarvinPinto Your code is not suitable with me. After the task, I need to pass the result Activity too. So I solved it by using another callback method. Thank you.
  • PankajAndroid
    PankajAndroid almost 11 years
    but if i want to use return value of AsyncTask and on the base of return value i wannt to call new URL so what can i do for this?? i think in this way we must have to use .get without it if there is any option then pls help me
  • Wonho Jung
    Wonho Jung over 6 years
    Another way : if your code executed on UI thread, wrap your AsyncTask by new thread... ex) new Thread(new Runnable(){.... result = yourAsyncTask.execute().get();.....}).start();
  • Ana
    Ana over 5 years
    Helped me after wasting 2 hours. Thanks.. :)