2

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

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

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

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

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

回答

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

这职位Runnable到UI线程如果方法调用被做了非UI线程,避免CalledFromWrongThreadException秒。

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

1

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

相反,请从内doInBackground()publishProgress(),您将收到UI线程在随后的回调中onProgressUpdate()在这里你可以修改ProgressBar,只要你喜欢。

+0

你的意思是'publishProgress()'而不是'refreshProgress()'? –

+0

是的,他的意思是publishProgress –