0

我試圖從我的TimerTask中更改我的UI,並且我認識到這是不可能的,因爲TimerTask在後臺線程中運行,後臺線程不允許更改UI。
現在我的問題是:我正在改變一個ProgressBar和一個TextView從TimerTask,它的工作ProgressBar但不適用於TextView。爲什麼我可以改變ProgressBar?Thread在android中的工作矛盾

爲什麼ProgressBar沒有任何問題呢?

timer.scheduleAtFixedRate(new TimerTask() { 
     @Override 
     public void run() { 
      int time = playerTimer(time); 

      progressbar.setProgress(time); 
      playerTime.setText(time); 

     } 

    }, 0, 1000); 

回答

1

並非所有的UI操作都必須在主線程上完成。可以從另一個線程調用的方法在主線程上調度View或View樹的佈局和/或繪製。在實踐中,嘗試辨別哪些方法可以安全地從非UI線程調用,哪些方法不安全並不是一個好主意。

要解決這個問題,你應該使用AsyncTask並從UI線程上運行回調裏面把你所有的UI操作:onPreExecute()onPostExecute()onProgressUpdate()

1

由於setProgress方法是同步的,這似乎是專爲從另一個線程調用。雖然文檔沒有明確說明。

1

ProgressBar class是爲了與它一起工作而設計的。下面是它的代碼:

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); //--posted to view's thread -- 
      mRefreshIsPosted = true; 
     } 
    } 

這是檢查您是否在UI線程上。如果不是它在UI線程上發佈可運行的。我的猜測是,這個設計可以幫助它從多個地方更新progressBar。

對於你所要做的其他觀點:

runonUiThread(new Runnable(){ 

@Override 
public void run(){ 
    //--- change the view-- 
} 

}); 
+0

謝謝你,這也是真的。 –