前言
点击Launcher的应用图标,到应用的主页展示到屏幕的过程中,Android系统是如何将画面渲染出来的?
本文将分析应用启动时View相关的代码,理解启动期间View的相关代码,理解View、Window、WindowManager、ViewRootImpl和Activity之间的关系。
启动
我们都知道Android应用进程的入口是ActivityThread的main方法。在经过与system_server的一系列IPC交互后,最终AMS会发起EXECUTE_TRANSACTION的命令,启动category为android.intent.category.LAUNCHER的Activity,走到了ActivityThread.performLaunchActivity方法:
1 | // ActivityThread.java |
从源码可以看到,在应用启动时,会调用到Activity的attach方法,之后马上就会回调Activity的onCreate方法,看看attach内部做了什么:
1 | // Activity.java |
可以看到,调用到Activity的attach方法时,会为Activity创建一个Window ,并为这个Window 设置好WindowManager 。
设置的WindowManager 是哪个类的实例?点进去看看:
1 | // Window.java |
原来WindownManager 是通过WindowManagerImpl的createLocalWindowManager创建而来的,而WindowManagerImpl的parentWindow,就是上面Activity在attach时创建的Window,即PhoneWIndow。
此后,performLaunchActivity结束,Activity的状态置为ON_CREATE。
AMS又再发起EXECUTE_TRANSACTION的命令,回调Activity的onStart方法,此时Activity开始可见:
1 | // ActivityThread.java |
至此,Activity开始可见,准备开始获取焦点。
获取焦点
AMS发起EXECUTE_TRANSACTION 的命令,试图将Activity的生命周期扭转为RESUMED 状态,于是代码就走到了ActivityThread的handleResumeActivity方法:
1 | // ActivityThread.java |
在handleResumeActivity中,从启动的activity中获取DecorView和WindowManager之后,会将DecorView 纳入WindowManager的管理。看看addView内部做了什么:
1 | // WindowManagerImpl.java |
mGlobal是WindowManagerGlobal ,如其命名,是一个进程下的全局WindowManager,维护View和Window的关系。
看看WindowManagerGlobal 的addView内部做了什么:
1 | // WindowManagerGlobal.java |
WindowManagerGlobal内部创建了一个ViewRootImpl实例,并把view,也就是DecorView给设置到ViewRootImpl里面去。setView十分重要,内部请求重新布局,并且Window开始获取焦点:
1 | // ViewRootImpl.java |
经过WindowSession的addToDispalyAsUser方法后,Window获取到了焦点,回调到DecorView 的onWindowFocusChanged。在获取焦点前,有一个关键的requestLayout方法,内部Choregrapher请求VSync信号后,就开始的View的三大流程:测量、布局和绘制。先看看VSync信号的请求流程。
VSync信号
requestLayout十分重要,内部先开启Handler的同步屏障,而后Choregrapher开始等待vsync信号,信号到达,回调TraversalRunnable,开始执行View树的遍历:
1 | // ViewRootImpl.java |
关键在postCallback,Choregrapher会在合适的时机回调TrasversalRunnable,会在什么时机?点进去看看:
1 | // Choregrapher.java |
从代码可以看出,postCallback内部调用到了scheduleFrameLocked,请求VSync信号。mDisplayEventReceiver内部调用了native方法,在此不做赘述。
VSync信号到达,会回调到FrameDisplayEventReceiver的onVsync方法:
1 | // Choregrapher.FrameDisplayEventReceiver.java |
VSync信号到达,FrameDisplayEventReceiver会发送一个带有callback的异步消息到Handler中,而后就会回调到FrameDisplayEventReceiver的run方法,执行Choregrapher的doFrame方法:
1 | // Choregrapher.java |
在doFrame内部调用到doCallbacks,doCallbacks内部Choregrapher会找到CALLBACK_TRAVERSAL类型的callback,并回调他的run方法,在CallbackRecord 内部会调用到真正的callback,也就是前面传入的mTraversalRunnable 。
至此,开始调用ViewRootImpl 的doTraversal方法,进一步调用performTraversal方法,正式进入View的三大流程: 测量、布局以及绘制:
1 | // ViewRootImpl.java |
总结
从上面的分析可知,一个Activity对应一个Window,这个Window就是PhoneWindow,而其管理类便是WindowManager,对应WindowManagerImpl。这个WindowManagerImpl内部持有一个WindowManagerGlobal,统一管理当前应用进程的所有Window 。
在Activity的Resume阶段,通过WindowManagerGlobal的addView将DecorView和ViewRootImpl绑定在一起,形成一个View树,最终调用requestLayout,启动View(DecorView)的三大流程:测量、布局以及绘制。
在启动阶段的整体流程:
- 在
Activity回调onCreate前,ActivityThread会为Activity创建一个Window,并为这个Window设置一个WindowManager; - 在
Activity回调onStart后,ActivityThread会把这个Activity设置为可见; - 在
Activity回调onResume后,会通过WindowManagerGlobal创建一个ViewRootImpl,此后通过ViewRootImpl请求第一次布局,在通过Choregrapher请求第一次VSync信号;之后收到VSync信号后,执行performTraversals,正式进入View的三大流程: 测量、布局以及绘制。
