冷启动就是在 Launcher 进程中开启另一个引用 Activity 的过程。这是一个 Launcher 进程和 AMS,应用进程和 AMS,WMS 双向通信的过程:

  • Launcher 进程和 AMS 说:“我要启动Activity1”
  • AMS创建出 Activity1 对应的 ActivityRecord 以及 TaskRecord,通知 Launcher 进程执行 onPause()
  • Launcher 执行 onPause(),并告知 AMS
  • 启动一个 starting window,AMS 请求 zygote 进程 fork一个新进程
  • 在新进程中,构建ActivityThread,并调用main(),在其中开启主线程消息循环。
  • AMS 开始回调Activity1的各种生命周期方法。
  • 当执行到 Activity.onAttch()时,PhoneWindow 被构建。
  • 当执行到 Activity.onCreate()时,setContentView()会被委托给 PhoneWindow,并在其中构建DecorView,再根据主题解析系统预定义文件,作为 DecorView 的孩子,布局文件中肯定有一个 id 为 content 的容器控件,他将成为 setContentView 的父亲。
  • 当执行到 Activity.onResume()时,DecorView 先被设置为 invisible,然后将其添加到窗口,此过程中会构建 ViewRootImpl 对象,它是 app 进行和 WMS 双向通信的纽带。ViewRootImpl.requestLayout()会被调用,以触发View树自顶向下的绘制。
  • View 树遍历,会被包装成一个任务抛给 Choreographer。在此之前 ViewRootImpl 会向主线程消息队列抛一个同步消息屏障。以达到优先遍历异步消息的效果。
  • Choreographer 将任务暂存在链式数组结构中,然后注册监听下一个 vsync 信号。
  • 待下一个 vsync 信号到来之时,Choreographer 会从链上摘取所有比当前时间更早的任务,并将他们包装成一个异步消息抛到主线程执行。
  • 异步消息的执行,即是从顶层视图开始,自顶向下,逐个视图进行 measure,layout,draw的过程。
  • ViewRootImpl 持有一个 surface,它是原始图形缓冲区的一个句柄,原始图形缓冲区是一块存放像素数据的内存地址,这块内存地址由app进程和SurfaceFlinger共享。当 app进程执行完上述步骤时,就意味着像素数据已经填入该块内存,于是 app 通知 SurfaceFlinger 像素数据已经就绪,可以进行合成并渲染到屏幕了。
  • 当 DecorView 完成渲染后,就会被设置为 visible,界面展示出来。