Android 里子线程真的不能刷新UI吗?
2016-04-16 14:54
483 查看
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."); } }
那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
相关文章推荐
- 《iOS Human Interface Guidelines》——Launch Files
- UI 布局
- iOS用ASIFormDataRequest实现图片上传
- 本地缓存以及UIDocumentInteractionController的使用
- UE4与WEB服务器交互(json)
- 【Arduino官方教程第一辑】示例程序 1-1 读取模拟信号、串口操作
- iOS 动画总结----UIView动画
- Android UI基础之Spinner
- UI- 五种手势识别总结
- poj 2264 Advanced Fruits lcs
- Android UI高级之Menu
- [学习笔记]easyui 为表格行添加事件
- Android UI高级之Notification
- UI- UINavigationController UITabBarController 使用总结
- How do I setup Git for an UE4 project?
- (LeetCode 304) Range Sum Query 2D - Immutable
- HDU-3732 Ahui Writes Word
- Android进阶-UIL分析
- JAVA——String与StringBuffer以及StringBuilder
- UVA 1151 Buy or Build(生成树+二进制枚举)