作为普通应用开发者,Andorid Framework是神秘的存在,但是不了解Andorid Framework,仅仅使用一些系统提供的API,很难在技术上有所突破。一直以来想写一些文章来记录自己学习Framework的过程,想过从View、Binder等方向入手开篇,但View绕不开Activity,Binder没有使用场景又过于难懂,因此决定从startActivity入手,由浅入深,一步一步揭开Framework的面纱。
Activity是四大组件中使用最频繁的,startActivity又是最基础的技能。作为App开发者来讲,Activity是熟悉而又陌生,熟悉是因为每天都在用,陌生是因为Andorid很多基础的API依赖于Activity,只知其然,而不知其所以然。下面列举一些问题:
- Activity实例在哪里构建的?
- setContentView干了什么?
- View是如何显示在Activity中的?
- Activity的生命周期函数如何调用的?
- Activity的启动权限有什么?
- 谁在管理着Activity?
- App进程如何和系统进程通讯?
- Activity在系统和App进程中的记录分别是什么?
- 系统为什么要管理Activity?
.....
类似的问题有很多,startActivity的源码并不能一一解答所有问题,但它能起到抛砖引玉的作用,了解了startActivity的过程,才能对Activity有一个理性的认知,才能继续分析这些问题。下面引用一张图来解释系统处理startActivity的重要性:
既然是源码分析,RTFSC (Read the fucking source code )是比不可少的。但在开始之前还是简述一下大致流程,并且用示意图表示其过程,便于理解。
Activity1表示调用startActivity的Activity,Activity2表示要启动的Activity。
- App进程侧收集Intent等信息,向AMS(系统进程中的ActivityManagerService)发送“启动Activity2”的信号
- AMS进行:Activity2的信息收集、uid和pid获取、权限检查、Task和mHistory的处理,创建了Activity2在AMS中的句柄ActivityRecord
- AMS尝试resume Activity2,但是发现需要先pause掉Activity1,随后向App进程发送“pause Activity2”的信号
- App进程收到信号后,在looper中处理pause消息,调用了Activity1的声明周期函数onPause
- App进程完成pause后,告诉AMS:“我已经pause完毕”
- AMS接收信号后,继续尝试resume Activity2,并且发现可以resume,便告诉App进程“你需要resume Activity2”
- App进程接收到信号后,依然在looper中处理,创建Activity2实例、依次调用onCreate、onResume生命周期函数
重点说明以下几点:
- Binder是跨进程通讯方式,使用起来是面向对象的,由于本文重点不在于Binder,因此可认为Binder的调用是无感的,但它确实完成了跨进程。同时这里的跨进程都是同步调用的。
- 源码分析使用API 16,这是因为低版本的代码更加精简,高版本的代码核心依然和低版本的一致,若分析高版本的源码,无疑会浪费精力