子线程能不能更新UI?
几个涉及的类说明
Window、PhoneWindow
PhoneWindow是Window子类
setContentView其实就是将View设置到Window上,Activity展示的其实是PhoneWindow上的内容
1 | //Activity.java |
WindowManager、WindowManagerService
WindowManager 父类是 ViewManager 实现类是WindowManagerImpl
WindowManager真正实现控制view添加删除更新
WindowManager和WindowManagerService的交互是一个IPC过程
1 | //Window.java 上面的代码块的方法跟进 |
WindowManagerGlobal
WindowManagerGlobal 真正实现了 WMImpl的 增删View的动作
1 | public final class WindowManagerImpl implements WindowManager { |
ViewRootImpl
1 | //WindowManagerGlobal.java |
总结
来自:https://www.cnblogs.com/mingfeng002/p/9143831.html
- 鉴于窗口布局和控件布局的一致性,WindowManager继承并实现了接口ViewManager。
- 使用者可以通过Context.getSystemService(Context.WINDOW_SERVICE)来获取一个WindowManager的实例。这个实例的真实类型是WindowManagerImpl。WindowManagerImpl一旦被创建就确定了通过它所创建的窗口所属哪块屏幕?哪个父窗口?
- WindowManagerImpl除了保存了窗口所属的屏幕以及父窗口以外,没有任何实质性的工作。窗口的管理都交由WindowManagerGlobal的实例完成。
- WindowManagerGlobal在一个进程中只有一个实例。
- WindowManagerGlobal在3个数组中统一管理整个进程中的所有窗口的信息。这些信息包括控件、布局参数以及ViewRootImpl三个元素。
- 除了管理窗口的上述3个元素以外,WindowManagerGlobal将窗口的创建、销毁与布局更新等任务交付给了ViewRootImpl完成。
handleLaunchActivity
启动Activity流程中 最后会调用到 handleLaunchActivity
在内部依次调用performLaunchActivity
和 handleResumeActivity
1 | //androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/app/ActivityThread.java |
1 | final void handleResumeActivity(IBinder token, |
总结
上面采用了瞎比倒叙法来说明,可能有点乱,这里总结理一下
handleResumeActivity
-> onResume
->WindowManagerImpl.addView(传入的是DecorView)
-> WindowManagerGlobal.addView()
->new ViewRootImpl()
-> ViewRootImpl.setView()
->requestLayout()
让我们回到最开始的问题:子线程能不能更新UI?
答案是能,在onCreate中更新ui,此时ViewRootImpl 还未被创建(onResume才创建),所以不会传到ViewRootImpl来实际绘制,更没有checkThread
来抛出异常,这样在正常流程开始绘制的时候,就会绘制子线程中更新进去的内容
setContentView
1 | //Activity |
scheduleTraversals
不管是requestLayout
还是requestFitSystemWindows
最后都是来到scheduleTraversals
方法中
1 | 1428 void scheduleTraversals() { |
performTraversals
是怎么开启每个view的 measure layout draw 的? 且听下回分解 饭点到了
performTraversals()中
使用performMeasure() 来测量View大小。
使用performLayout()来确定View的绘制区域。
使用performDraw()来真正的绘制