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 –