在AsyncTask doInBackground()中更新进度条?

时间:2013-08-26 21:16:37

标签: android multithreading android-asynctask android-progressbar

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

我有一个AsyncTask,它在doInBackground()中移动了一堆文件。我有一个进度条,代表用户。

对于它(主要是由于懒惰)我决定在doInBackground()方法/线程中尝试progressBar.setProgress([更新进度]),令我惊讶的是,它工作正常。

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

我是否应该在此后台线程中更新进度条?

2 个答案:

答案 0 :(得分:3)

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 线程,则会向{0}发布Runnable,以避免CalledFromWrongThreadException

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

答案 1 :(得分:1)

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

相反,从publishProgress()内部调用doInBackground(),您将在onProgressUpdate()中的UI线程上收到后续回调,您可以根据需要修改ProgressBar。< / p>