Android 里子线程真的不能刷新UI吗?
来源:互联网 发布:mac 查找java安装路径 编辑:程序博客网 时间:2024/04/30 17:31
Android 里子线程真的不能刷新UI吗?
在开发应用中,如果子线程中更新UI会抛出异常,但并不是因为只有UI线程才能更新UI,
而是因为ViewRootImpl会进行检查,如果 mThread!=当前线程 时会抛出异常CalledFromWrongThreadException异常
ViewRootImple.java
void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); }}
ViewRootImple.setView() -> requestLayout() 中有调用checkThread()
那mThread是什么呢?
通过ViewRootImpl的构造函数我们可以发现mThread会被赋值为创建ViewRootImp的那个线程
public ViewRootImpl(Context context, Display display) { mContext = context; mWindowSession = WindowManagerGlobal.getWindowSession(); //此处进行mThread的赋值 mThread = Thread.currentThread(); //代码省略...}
而ViewRootImpl是在主线程中创建的,所以,才需要在主线程中更新UI
不过,设定为在主线程更新UI也是为了安全和简化起见吧
那么,能否在子线程中更新UI呢
如果ViewRootImpl是由子线程创造的,那么自然可以在该子线程中更新UI
但是如果我们直接创建ViewRootImpl实例的话,会发现找不到该类。
可以通过WindowManager.addView来间接创建一个ViewRootImpl
比如
class TestThread1 extends Thread{ @Override public void run() { Looper.prepare(); TextView tx = new TextView(MainActivity.this); tx.setText("test11111111111111111"); WindowManager wm = MainActivity.this.getWindowManager(); WindowManager.LayoutParams params = new WindowManager.LayoutParams( 250, 250, 200, 200, WindowManager.LayoutParams.FIRST_SUB_WINDOW, WindowManager.LayoutParams.TYPE_TOAST,PixelFormat.OPAQUE); wm.addView(tx, params); Looper.loop(); }}
MainActivity是建立android工程时生成的入口类,TestThread1是MainActivity的内部类。感兴趣的话,试试吧!看看是不是在屏幕上看到了”test11111111111111111”?
具体创建ViewRoot的地方在wm.addView(tx, params)
具体流程:
WindowManagerImpl.addView(View view, ViewGroup.LayoutParams params)
->
WindowManagerImpl.addView(View view, ViewGroup.LayoutParams params, boolean nest)
代码(精简):
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; ViewRootImpl root; View panelParentView = null; synchronized (mLock) { //新建ViewRootImpl root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); } root.setView(view, wparams, panelParentView);}
其他
参考
http://www.oschina.net/question/54100_29585
- Android里子线程真的不能刷新UI吗?
- Android 里子线程真的不能刷新UI吗?
- Android 中非UI线程真的不能更新UI吗?
- android 子线程真的不能更新ui吗
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android中子线程真的不能更新UI吗?
- Android 真的不能在子线程更新 UI 吗
- 非UI线程真的不能更新UI吗?
- Android子线程真的不能更新UI么
- Android子线程真的不能更新UI么
- rsync数据备份(三)--非系统用户备份数据--RHEL6.5
- C++ STL泛型编程——在ACM中的运用
- socket关闭
- 数理统计——频数和相关系数
- 《LeetBook》leetcode题解(12):Integer to Roman[M]
- Android 里子线程真的不能刷新UI吗?
- nyoj_183_赚钱啦
- VisualSVN-Server安装图解
- Mybatis各种模糊查询
- 网页资料搜集站
- springMVC原理
- 数据缓存以及存取
- sed用法总结
- Ubuntu 下配置 PhpStorm 自动编译 LESS 生成css和source-map