一、Activity的启动流程
- Launcher会通过Binder向AMS发送startActivity请求;
- AMS收到请求后通过socket通知Zygote fork App进程;
- App进程通过Binder向AMS发起attachApplication;
- AMS收到attachApp的请求后,通过Binder向App进程发送scheduleLaunchActivity;
- App收到消息后,通过Handler向ActivityThread发送LAUNCH_ACTIVITY消息;
- ActivityThread收到消息后,反射创建目标Activity,并回调onCreate方法;
思考: 为什么AMS和Zygote之间要用socket通信,而不用binder呢?
- 先后时序问题:AMS无法获取到Zygote的Binder引用。因为Binder驱动早于init进程加载,init先创建ServiceManager,再创建Zygote,期间不能保证Zygote注册binder的时候,ServiceManager已经初始化好了。;
- 多线程问题:Zygote如果使用了Binder,会导致子进程中的Binder线程的挂起和锁状态不可恢复。Zygote的fork,只考虑了主线程的fork,如果存在子线程,那么子线程的锁和挂起状态不可恢复;
- 效率问题:AMS和Zygote间使用的是LocalSocket,减少数据验证环节,效率不低;
- 安全问题:LocalSocket有权限校验;
- 拷贝问题:Zygote fork App进程后,App进程会主动关闭掉socket,释放该区域;而Binder如果要释放app server端的binder引用,就必须释放AMS的client端对象,从而导致AMS无法向Zygote发消息;
二、Activity的生命周期
- A->B: A onPause ->B onCreate ->B onStart ->B onResume ->A onStop;
- 配置发生变化:onPause -> onStop -> onSaveInsanceState -> onDestroy;
- 配置变化重新创建:onCreate -> onStart -> onRestoreInstanceState ->onResume
思考: 缓存时机与恢复数据的流程?
- onSaveInstanceState会自动收集View Hierachy中每一个完成状态保存与恢复的View.
- onSaveInstanceState数据最终储存到AMS的ActivityRecord中。杀死进程依然存在;
- 再onRestoreInstanceStates时会依据View的id逐一匹配的回传给每一个View;
onSaveInstanceState和onRetainNonConfigurationInstance区别? onSaveInstanceState数据保存到bundle中,最终存到系统进程中,app被杀可以恢复; onRetainNonConfigurationInstance可以保存任何类型的数据,最终存到app进程中,app被杀不可恢复;
三、Activity启动模式
- standard:会在启动该Activity的任务栈中创建一个新Activity,成为栈顶;
- singleTop:启动者所在的任务栈顶部存在目标Activity,系统会调用其onNewIntent()将intent传送给该实例并复用。
- singleTask:目标任务栈存在目标Activity,系统会弹出目标Activity之上的所有实例。可以通过声明taskAffinity在一个特定的任务栈中启动,且允许其他实例共享同一任务栈,若不声明,taskAffinity为applicationId.
- singleInstance:启动的Activity会独占一个任务栈,由该实例启动的任何实例,都在其他任务栈中打开;
- startActivityForResult:在api20以上,singleTask和singleInstance启动的实例都不会新建一个任务,还是在原来的栈中。
四、onDestroy的执行时机
- 在handleResumeActivity方法中,完成绘制和显示后,会添加一个闲时任务。在主线程空闲时会调用;
- 如果主线程无法空闲,onDestroy执行时机就会延迟。
- 这种情况下,系统会提供一个兜底机制,当resume 10s后,仍然没有空闲,则会主动触发。