您的位置:首页 > 产品设计 > UI/UE

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

2015-03-05 13:48 453 查看
今天我qq群里面的大漠同学问了这样一个问题,先看看他粘贴的源代码如下:

[java] view
plaincopy

TimerTask task = new TimerTask() {  

            public void run()  

                {  

                    if (timeFlag)  

                    {  

                        if (timeRemain > 0)  

                        {  

                            timeRemain -= 1;  

                            timeProgress.setProgress(timeRemain);  

                              

                        }  

                        else  

                        {  

                            if (!bDialogShow)  

                            {  

                                bDialogShow = true;  

                                gameView.isgameover = true;  

                                mHandler.sendEmptyMessage(MSG_RESULT_DIALOG_SHOW);  

                            }  

                        }  

                    }  

                }  

        };  

          

timer = new Timer();  

timer.schedule(task, 0, 1000);  

他的问题和疑惑是:

这个为什么没报错啊  ?

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
plaincopy

private synchronized void refreshProgress(int id, int progress, boolean fromTouch) {  

        if (mUiThreadId == Thread.currentThread().getId()) {  

            doRefreshProgress(id, progress, fromTouch);  

        } else {  

            RefreshProgressRunnable r;  

            if (mRefreshProgressRunnable != null) {  

                // Use cached RefreshProgressRunnable if available  

                r = mRefreshProgressRunnable;  

                // Uncache it  

                mRefreshProgressRunnable = null;  

                r.setup(id, progress, fromTouch);  

            } else {  

                // Make a new one  

                r = new RefreshProgressRunnable(id, progress, fromTouch);  

            }  

            post(r);  

        }  

    }  

从源代码里面我们可以看到当当前刷新的线程不是主线程的时候,ProgressBar会去自动new一个刷新的线程,所以这和刷新的时候在不在主线程里面调用setProgress方法关系不大,从表面上看似乎是在非UI线程里面去修改了主线程的控件,而实际上并非这样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: