在Activity中调用setContentView,会将操作交给PhoneWindow处理,在PhoneWindow的setContentView方法中,先创建出DecorView,DecorView是FrameLayout的子类,默认有一个mContentParent对象,然后将xml中的布局添加到mContentParent中。如图:
在activity的onCreate阶段只是初始化需要显示的内容,而在onResume阶段才会将PhoneWindow中的DecorView绘制到屏幕。在ActivityThread的handleResumeActivity方法中,会调用WindowManager的addView将DecorView添加到WMS,最终调用到WindowManagerGlobal的addView方法中,WindowManagerGlobal是一个单例,每个进程只有一个实例对象,在他的addView方法中,会创建出ViewRootImpl对象,然后通过ViewRootImpl的setView方法将view添加到WMS。在setView方法中,先通过requestLayout方法执行View的测量布局绘制流程,然后调用mWindowSession的addToDisplay方法将view添加到WMS,最终会通过aidl调用WMS的addWindow方法。另外在setView中还会创建出InputChannel,通过socket的方式接收WMS发送过来的触摸事件,首先是DecorView接收到事件,DecorView再通过dispatchPointerEvent和自己重写的dispatchTouchEvent方法将事件传给对应的activity或者dialog,activity再调用PhoneWindow的superDispatchTouchEvent将事件往view进行分发。
requestLayout过程
requestLayout过程包括view的测量、布局和绘制。首先是检查线程,检查当前线程是否是创建ViewRootImpl的线程,一般来说就是指主线程,如果不是就抛出异常(如果想实现在子线程更新UI,可以创建一个子线程,开启Handler的Looper循环,然后在这个子线程创建的view,就可以在这个子线程更新UI)。然后往主线程消息队列中发送同步屏障消息,接着Choreographer监听垂直同步消息后发送异步消息处理UI,同步屏障的目的是保证处理UI的消息优先执行。主线程接收到处理UI的消息后,最终会调用到performTraversals方法,在这个方法中执行测量布局绘制。