非UI线程可以去刷新UI吗(timertask调用progressbar的setProgress的特例)
2012-11-01 12:45
429 查看
今天我qq群里面的大漠同学问了这样一个问题,先看看他粘贴的源代码如下:
他的问题和疑惑是:
这个为什么没报错啊 ?
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) 方法,下面我附上源代码:
从源代码里面我们可以看到当当前刷新的线程不是主线程的时候,ProgressBar会去自动new一个刷新的线程,所以这和刷新的时候在不在主线程里面调用setProgress方法关系不大,从表面上看似乎是在非UI线程里面去修改了主线程的控件,而实际上并非这样。
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) 方法,下面我附上源代码:
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线程里面去修改了主线程的控件,而实际上并非这样。
相关文章推荐
- 非UI线程可以去刷新UI吗(timertask调用progressbar的setProgress的特例)
- ProgressBar可以在子线程更新UI
- 主线程、子线程都可以调用的UI变更方法
- Android子线程其实也可以刷新UI。。。。
- TimerTask()中调用TextView.setText报错原因(非UI线程中 不能访问UI组件)
- 在非UI线程中调用ProgressBar的setProgress函数,刷新进度条
- 子线程是否可以刷新UI视图?
- c#利用委托跨线程调用UI控件完整使用方法
- ex = {"在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。 解决办法
- 开源项目OkHttpPlus——支持GET、POST、UI线程回调、JSON格式解析、链式调用、文件上传下载
- 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常
- WPF 之 调用线程必须为 STA,因为许多 UI 组件都需要
- 非 UI 线程 调用 Toast的问题
- Timer和TimerTask与线程的关系
- iOS GCD子线程调用主线程刷新
- 在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常
- 再谈子线程-居然可以在非UI线程中更新UI
- Android在后台线程和timertask分别实现定期更新时间
- Android 非UI线程是否可以更新UI
- struts也可以使用ajax异步调用页面局部刷新