调用AsyncTask.get()时未显示ProgressDialog

时间:2012-01-26 14:04:24

标签: android android-asynctask progressdialog

  

可能重复:
  AsyncTask block UI threat and show progressbar with delay

我想在从任何服务器检索JSON时显示progressDialog。所以我使用AsyncTask作为解决方案(不确定任何不同的出路)。

一切都很好,ProgressDialog正常工作,直到我使用AsyncTask实例调用.get()方法。我想它会以某种方式阻止UI。这是我的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();
    }
}

这是调用AsyncTask的myActivity:

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

执行后,当我尝试从doInBackground和onPostExecute记录结果时,都没有问题。但是如果我想使用.get(),结果ProgressDialog没有显示或显示的时间很短(可能是0.2秒)

有什么问题?

4 个答案:

答案 0 :(得分:26)

是的,如果需要完成计算,get() 等待,然后检索其结果。这意味着,您正在阻止您的UI线程,等待结果。

解决方案:请勿致电get

通常,您将在postExecute

中调用函数(回调)

答案 1 :(得分:16)

调用.get()会将您的AsyncTask更改为有效的“SyncTask”,因为它会导致当前线程(可能是UI线程)等到AsyncTask完成了它的处理。由于您现在正在阻止UI线程,因此对ProgressDialog的{​​{1}}方法的调用永远不会允许对话框自己绘制屏幕。

删除呼叫将允许它在后台正常运行。

如果您需要在任务完成后进行处理,我建议您将其放入.show()方法本身或使用onPostExecute Activity的回调。

答案 2 :(得分:4)

如果我正确理解您的问题,您需要在ProgressDialog中更新AsyncTask的进度,而这当前不起作用。所以要注意几点:我不确定你要用.get()做什么,但我会假设你想要显示进度。

我已修改下面的程序,用AsyncTask的进度更新UI线程。每当您需要更新进度时,请在prog方法中更新doInBackground变量。

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();
  }
}

答案 3 :(得分:-2)

尝试使用runOnUiThread:

         runOnUiThread(new Runnable(){
            public void run() {
                dialog.show();
                }});    

在AsyncTask上运行某些东西意味着它从UIthread运行,所以通常你不能从Async方法内部运行ui操作,而没有处理程序和我通常远离的东西。我也通过在我的oncreate上面创建一个progressDialog作为变量来处理这样的解决方案,因此它对整个类都是可见的。然后我在我的asynctask之前调用progressdialog,然后因为它对整个类可见,我在onPostExecute中调用.dissmiss()