Android子线程中更新UI的方法
来源:互联网 发布:速拓必达医疗器械软件 编辑:程序博客网 时间:2024/06/02 19:36
1.handler
2.通过runOnUiThread方法
方法内部实现如下:public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); } else { action.run(); } }使用方法如下:
new Thread(new Runnable() { @Override public void run() { // 此处执行耗时操作,结束后,执行runOnUiThread将线程切换到主线程去更新ui runOnUiThread(new Runnable() { @Override public void run() { // 更新ui操作 } }); } }).start();如果在非上下文中环境中,可以通过一下方法来实现:
final Activity activity = (Activity) mTextView.getContext(); new Thread(new Runnable() { @Override public void run() { activity.runOnUiThread(new Runnable() { @Override public void run() { } }); } }).start();
在其他地方,则需要传递Activity对象,因为runOnUiThread方法是Activity的方法。
3.通过view.post(runnable)来实现
mTextView.post(new Runnable() { @Override public void run() { } });
4.子线程直接更新ui的极端情况
android的UI访问是没有加锁的,这样会导致多个线程访问ui会不安全,那么既然这样,为什么不加锁呢,因为加上锁机制会让ui访问的逻辑变得复杂,其次锁机制会降低ui访问的效率,锁机制会阻塞某些线程的执行。所以android规定,只能在主线程更新ui。
子线程真的无法更新ui吗,答案是no,因为有些极端情况,还是可以更新ui的。
我们在onCreate中直接执行以下代码:
Log.i("niejianjian", " -> onCreate -> " + Thread.currentThread().getId()); new Thread(new Runnable() { @Override public void run() { Log.i("niejianjian", " -> Thread -> " + Thread.currentThread().getId()); mTextView.setText("fjsdlj l"); } }).start();发现更新ui是可以成功的,我们可以打印当前的线程,发现确实是在子线程中,因为主线程的id是1。但是我们在将Thread睡眠200ms,
Log.i("niejianjian", " -> onCreate -> " + Thread.currentThread().getId()); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } Log.i("niejianjian", " -> Thread -> " + Thread.currentThread().getId()); mTextView.setText("fjsdlj l"); } }).start();结果就报错了,log如下:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6257) at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:868)ViewRootImpl是ViewRoot的实现类,异常主要是checkThread抛出的,因为里面对线程做了判断:
void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); }}因为view的绘制过程中,都会执行ViewRootImpl的checkThread来检查是否是主线程更新,所以onCreate中的子线程可以更新ui,主要是因为ViewRootImpl还没有创建,所以无法进行检查。
ViewRootImpl的创建在onResume方法回调之后,而我们一开篇是在onCreate方法中创建了子线程并访问UI,在那个时刻,ViewRootImpl是没有创建的,无法检测当前线程是否是UI线程,所以程序没有崩溃一样能跑起来,而之后修改了程序,让线程休眠了200毫秒后,程序就崩了。很明显200毫秒后ViewRootImpl已经创建了,可以执行checkThread方法检查当前线程。
参考:http://www.cnblogs.com/xuyinhuan/p/5930287.html
0 0
- android子线程中更新UI的方法
- android子线程中更新UI的方法
- Android子线程中更新UI的3种方法
- Android子线程中更新UI的3种方法
- Android子线程中更新UI的3种方法
- Android子线程中更新UI的3种方法
- Android子线程中更新UI的3种方法
- Android子线程中更新UI的3种方法
- android-----在子线程中更新UI操作的方法
- Android子线程中更新UI的3种方法
- Android子线程中更新UI的3种方法
- Android子线程中更新UI的3种方法
- Android子线程中更新UI的方法
- Android子线程中更新UI的3种方法
- Android子线程中更新ui的方法
- Android子线程更新UI的方法
- Android在子线程中更新Activity中UI的方法
- Android在子线程中更新Activity中UI的方法
- IQKeyboardManager的使用笔记
- 如何做缓存
- C语言-倒计时操作操作
- Java多线程之死锁
- OpenStack CDNaaS - Poppy介绍
- Android子线程中更新UI的方法
- spark 将dataframe数据写入Hive分区表
- Untiy轻量级网络开发-Tnet客户端服务器编程
- Android 实现按钮自定义风格
- 解决WebView加载的网页被放大的问题
- Matlab连接MySQL数据库入门
- [生存志] 第92节 纵横游说之辞
- [JAVA] float,double计算方法
- Android 五子棋开发经验