AsyncTask 中的 ProgressDialog 未更新

发布于 2024-12-21 10:50:28 字数 1974 浏览 0 评论 0原文

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

进度对话框在任务的第一部分期间正确更新,但在第 2dn 部分期间不正确更新。 我尝试移动 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
      }
   }
}

I am having a problem with ProgressDialog UI being frozen when I start the action in the AsyncTask.
My problem is somewhat different than the bunch of other similar question because the my background task consists of two parts:
- first part (loadDB()) is related to the database access
- second part (buildTree()) is related to building the ListView contents and is started with runOnUiThread call

The progress dialog is correctly updated during the 1st part of the task, but not during the 2dn part.
I tried moving the buildTree part in the AsyncTask's onPostExecute but it doesn't help, this part of the code still causes the progress to freeze temporarily until this (sometimes quite lengthy) part of the work is done. I can not recode the buildTree part from scratch because it is based on external code I use.

Any tips on how to resolve this? Is there a method to force updating some dialog on screen?

The code goes here:

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
      }
   }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若言繁花未落 2024-12-28 10:50:29

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

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

类似这样的内容:

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
    }
}

You should call AsyncTask's publishProgress method and not the progDialog.setProgress(0); as you call.
Also the buildTree shouln't run on the UI thread since it will block it.
run the logic from the doInBackground method.

note that you don't actually build the ListView, rather you should build it's data model.
look here

something like this:

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
    }
}
凝望流年 2024-12-28 10:50:28

不要在 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);
    }
}

Don't run your whole buildTree() method inside the UI thread.

Instead, run only the changes you want to make to the UI in the UI thread:

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

And then:

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文