非UI线程可以去刷新UI吗(timertask调用progressbar的setProgress的特例)

今天我qq群里面的大漠同学问了这样一个问题,先看看他粘贴的源代码如下:

[java]  view plain copy
  1. TimerTask task = new TimerTask() {  
  2.             public void run()  
  3.                 {  
  4.                     if (timeFlag)  
  5.                     {  
  6.                         if (timeRemain > 0)  
  7.                         {  
  8.                             timeRemain -= 1;  
  9.                             timeProgress.setProgress(timeRemain);  
  10.                               
  11.                         }  
  12.                         else  
  13.                         {  
  14.                             if (!bDialogShow)  
  15.                             {  
  16.                                 bDialogShow = true;  
  17.                                 gameView.isgameover = true;  
  18.                                 mHandler.sendEmptyMessage(MSG_RESULT_DIALOG_SHOW);  
  19.                             }  
  20.                         }  
  21.                     }  
  22.                 }  
  23.         };  
  24.           
  25. timer = new Timer();  
  26. timer.schedule(task, 01000);  

他的问题和疑惑是:

这个为什么没报错啊  ?
timeProgress.setProgress(timeRemain);------不是说不能在非UI线程里更新View吗?

ok,下面我们来具体分析一个这个问题:

我知道我们都有一个这样的准则就是在android里面非ui线程是不能去修改ui线程里面的ui控件的

但问题的事实在这里,却和我们想象的有一定差异,那么问题的具体原因在哪里呢?或者更多的朋友把问题都归结为timertask就运行在主线程里面或者其它,而忽略了一个很重要的东西:在timertask的run方法里面的setprogress(int)方法,为了更好的有助于我们分析,在查看源代码之后我们可以知道这个方法会调用到private synchronized void refreshProgress(int id, int progress, boolean fromTouch) 方法,下面我附上源代码:

[java]  view plain copy
  1. private synchronized void refreshProgress(int id, int progress, boolean fromTouch) {  
  2.         if (mUiThreadId == Thread.currentThread().getId()) {  
  3.             doRefreshProgress(id, progress, fromTouch);  
  4.         } else {  
  5.             RefreshProgressRunnable r;  
  6.             if (mRefreshProgressRunnable != null) {  
  7.                 // Use cached RefreshProgressRunnable if available  
  8.                 r = mRefreshProgressRunnable;  
  9.                 // Uncache it  
  10.                 mRefreshProgressRunnable = null;  
  11.                 r.setup(id, progress, fromTouch);  
  12.             } else {  
  13.                 // Make a new one  
  14.                 r = new RefreshProgressRunnable(id, progress, fromTouch);  
  15.             }  
  16.             post(r);  
  17.         }  
  18.     }  

从源代码里面我们可以看到当当前刷新的线程不是主线程的时候,ProgressBar会去自动new一个刷新的线程,所以这和刷新的时候在不在主线程里面调用setProgress方法关系不大,从表面上看似乎是在非UI线程里面去修改了主线程的控件,而实际上并非这样。

你可能感兴趣的:(非UI线程可以去刷新UI吗(timertask调用progressbar的setProgress的特例))