【问题标题】:Updating progressbar in AsyncTask doInBackground()?在 AsyncTask doInBackground() 中更新进度条?
【发布时间】:2013-08-26 21:16:36
【问题描述】:

我在开始 android 开发(以及一般的初学者开发)时学到的第一件事是 UI 不应该(并且在许多情况下不能)由除了主 UI 线程之外的任何其他线程更新。

我有一个 AsyncTask 正在其 doInBackground() 中移动一堆文件。我有一个向用户表示的进度条。

为了它(主要是因为懒惰),我决定在 doInBackground() 方法/线程中尝试 progressBar.setProgress([updated progress]),令我惊讶的是,它工作正常。

但是,这似乎与我所学的惯例背道而驰。我知道 AsyncTask 有一个 onProgressUpdate() 或其他什么,但这让我有点困惑,我不确定它是否值得切换,因为当前的实现似乎工作正常。

我不应该在这个后台线程中更新进度条吗?

【问题讨论】:

    标签: android multithreading android-asynctask android-progressbar


    【解决方案1】:

    ProgressBar 能够做到这一点而不会崩溃,因为 setProgress() 调用 refreshProgress()(一种线程安全的方法),当需要真正刷新视图时。

    private synchronized void refreshProgress(int id, int progress, boolean fromUser) {
            if (mUiThreadId == Thread.currentThread().getId()) {
                doRefreshProgress(id, progress, fromUser, true);
            } else {
                if (mRefreshProgressRunnable == null) {
                    mRefreshProgressRunnable = new RefreshProgressRunnable();
                }
    
                final RefreshData rd = RefreshData.obtain(id, progress, fromUser);
                mRefreshData.add(rd);
                if (mAttached && !mRefreshIsPosted) {
                    post(mRefreshProgressRunnable);
                    mRefreshIsPosted = true;
                }
            }
        }
    

    如果方法调用是非UI线程,它会向UI线程发布Runnable,避免CalledFromWrongThreadExceptions。

    但是,总是使用 UI 线程进行 UI 相关的调用; Android 开发人员可以随时更改实现,而视图通常不是线程安全的。

    【讨论】:

      【解决方案2】:

      您不应修改ProgressBar 和/或直接从doInBackground() 内部调用其任何方法,因为Android UI 工具包不是线程安全的。

      相反,从doInBackground() 内部调用publishProgress(),您将在onProgressUpdate() 的UI 线程上收到后续回调,您可以随意修改ProgressBar

      【讨论】:

      • 您的意思是publishProgress() 而不是refreshProgress()
      猜你喜欢
      • 2011-12-17
      • 1970-01-01
      • 2019-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多