【问题标题】:ProgressDialog within AsyncTask not updatedAsyncTask 中的 ProgressDialog 未更新
【发布时间】:2011-12-16 11:00:38
【问题描述】:

当我在 AsyncTask 中启动操作时,我遇到了 ProgressDialog UI 被冻结的问题。 我的问题与其他类似问题有些不同,因为我的后台任务由两部分组成: - 第一部分 (loadDB()) 与数据库访问有关 - 第二部分 (buildTree()) 与构建 ListView 内容有关,并以 runOnUiThread 调用开始

进度对话框在任务的第一部分正确更新,但不是在第二部分。 我尝试在 AsyncTask 的 onPostExecute 中移动 buildTree 部分,但它没有帮助,这部分代码仍然会导致进度暂时冻结,直到完成这部分工作(有时很长)。我无法从头开始重新编码 buildTree 部分,因为它基于我使用的外部代码。

关于如何解决这个问题的任何提示?有没有办法强制更新屏幕上的某些对话框?

代码在这里:

public class TreePane extends Activity {

   private ProgressDialog progDialog = null;

   public void onCreate(Bundle savedInstanceState) {
       // first setup UI here
       ...

       //now do the lengthy operation
       new LoaderTask().execute();
   }

   protected class LoaderTask extends AsyncTask<Void, Integer, Void>
   {
        protected void onPreExecute() {
           progDialog = new ProgressDialog(TreePane.this);
           progDialog.setMessage("Loading data...");
           progDialog.show();
        }

        protected void onPostExecute(final Void unused) {
            if (progDialog.isShowing()) {
               progDialog.dismiss();
            }
        }

        protected void onProgressUpdate(Integer... progress) {
             //progDialog.setProgress(progress[0]);
        }

        protected Void doInBackground(final Void... unused) 
        {
            //this part does not block progress, that's OK
            loadDB();

            publishProgress(0);

            //long UI thread operation here, blocks progress!!!!
            runOnUiThread(new Runnable() {
                public void run() {
                   buildTree();
                }
            });

            return null;
        }
   }

   public void buildTree()
   {
      //build list view within for loop
      int nCnt = getCountHere();
      for(int =0; i<nCnt; i++)
      {
         progDialog.setProgress(0);
         //add tree item here
      }
   }
}

【问题讨论】:

    标签: android android-asynctask progressdialog


    【解决方案1】:

    不要在 UI 线程中运行整个 buildTree() 方法。

    相反,只在 UI 线程中运行您想要对 UI 进行的更改:

    protected Void doInBackground(final Void... unused) 
    {
        //this part does not block progress, that's OK
        loadDB();
        publishProgress(0);
        buildTree();
        return null;
    }
    

    然后:

    public void buildTree()
    {
        //build list view within for loop
        int nCnt = getCountHere();
        for(int =0; i<nCnt; i++)
        {
            progDialog.setProgress(0);
            runOnUiThread(new Runnable() {
                public void run() {
                    // update your UI here and return
                }
            });
            // now you can update progress
            publishProgress(i);
        }
    }
    

    【讨论】:

      【解决方案2】:

      你应该调用 AsyncTask 的 publishProgress 方法而不是 progDialog.setProgress(0);正如你所说。 buildTree 也不应该在 UI 线程上运行,因为它会阻塞它。 从 doInBackground 方法运行逻辑。

      请注意,您实际上并没有构建 ListView,而是应该构建它的数据模型。 look here

      类似这样的:

      protected Void doInBackground(final Void... unused) 
      {
          //this part does not block progress, that's OK
          loadDB();
          publishProgress(0);
          buildTree();
      }
      
      public void buildTree()
      {
          //build list view within for loop
          int nCnt = getCountHere();
          for(int =0; i<nCnt; i++)
          {
              publishProgress(i); //for exmple...
              //add tree item here
          }
      }
      

      【讨论】:

      • 如上所述,buildTree() 是我使用的外部代码,因此重写代码可能不是一件容易的事。不过感谢您的指点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-13
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多