Android 手机上电到 App 启动到 界面刷新全过程
手机启动流程
Android 是裁剪优化版的Linux 操作系统,手机开机上电后,先调起Bootloader 初始化硬件设备,挂在文件系统等。。。之后加载Kernel 内核,执行init() 第一个进程,启动基础进程和服务,广播、音媒体、zygote等。Zygote 会fork system_server进程 开启framework 层的各个服务进程 电池 加载资源 传感器 蓝牙。。。。 其中ActivityManagerService 启动之后会 恢复最近的task,webview,System UI ,最后启动Launcer App.
App 启动流程
Launcher 本身就是个App,一个独立的进程。每个应用安装的时候 桌面点击App Icon ,ActivityManagerService 会保存已经打开的App 的记录信息(uid+ Application 中的 process),如果没有已经打开的App,则zygote 会fork一个新的进程。ActiviyThread类加载到新进程中,并调用ActivityThread.main(); (传说中的 主线程 ~~~),接着创建ApplicationThread ,之后会毁掉oncreate(); onSetContentView(); onResum(); 它不是一个线程,它是运行在 App 进程中的主线程中的一个方法中。当 App 进程创建时会执行 ActivityThread.main(),ActivityThread.main() 首先会创建 Looper 执行 Looper.prepareMainLooper();然后创建 ActivityThread 并调用 ActivityThread.attach() 方法告诉 ActivityManagerService 我们创建了一个应用 并将 ApplicationThread 传给 ActivityManagerService;最后调用 Looper.loop()。
View初始化及刷新流程
Activity 初始化 setContentView() 的时候 ,会初始化一个Windows 子类PhoneWindows的对象,通过一个Token(IBinder对象)来与WindowsManagerService来通信, phoneWindows addView()的时候 会创建ViewRootImpl 对象来管理DecorView. 每个Activity对应一一个DecorView 为根布局的view 树,所有的管理都有ViewRootImpl负责。
一个基础概念 60 FPS : 60 frames per second. 每秒屏幕刷新画面的频率。
60 FPS, 是手机上人眼体验流畅的基本值,可以更高的频率。
60 FPS, 1000ms / 60 ≈ 16.67 意味着 刷新界面操作在 16ms 以内,用户才能感觉app流程。
至于为什么是60,人体奏这样呗。
Google 出过一个短视频,介绍了 Why 60 fps,
有条件翻墙的同学可以去看看 :https://www.youtube.com/watch?v=CaMTIgxCSqU
cpu 计算activity要显示的数据, gpu 进一步处理 backBuffer framBuffer数据缓存 ,Display 则从frameBuffer中读取缓存显示到屏幕上。 底层每个16.6ms 会发送一个 垂直信号VSync, Cpu 会在接收信号一开始就 处理要显示的数据,如果16.6ms 内没处理完成则会等待县一个信号显示。如果当前界面没有变化,则会是用之前的缓存显示界面。
一个View 绘制3个过程 onMeare() onLayout() onDraw(),若某个veiw invalidate(),则会 不断遍历 parentView tree知道DecoreView,ViewRootImpl接受到信息,则会最终调用到native 方法 发送刷新view 的Vsync事件。 一旦刷新 就会刷新此DecorVIew 树下所有view 。
所以布局尽量减少层级,尽量减少主动的 invalidate(),以优化性能体验。
ps: