咱们就以一场精彩纷呈的“舞台剧”为例,来生动演绎AMS和WMS是如何协同工作,指挥Activity完成生命周期切换的。这场剧的核心角色和场景如下:
| 角色/场景 | 比喻 |
|---|---|
| Activity | 台上的演员,负责表演(展示UI、处理交互) |
| ActivityThread | 演员的私人经纪人,负责直接与演员沟通,传达指令和安排行程 |
| ApplicationThread | 经纪人的专用电话接线员(一个Binder对象),负责接收外部来电 |
| AMS (ActivityManagerService) | 总导演,坐在系统进程(system_server)这个后台指挥部里,手握所有剧本和演员调度大权 |
| WMS (WindowManagerService) | 舞台监督,负责管理舞台上的窗口(Window)、灯光、焦点以及观众的视线 |
| Binder IPC | 角色之间高效的对讲机系统 |
| 主线程消息队列 (Looper/Handler) | 经纪人手中的日程表,任务按顺序排队处理 |
| Lifecycle Methods | 演员需要执行的不同表演指令(onCreate、onStart等) |
现在我们来看一场“从Activity A切换到Activity B”的精彩演出。
🎭 第一幕:换角指令的发出(StartActivity)
-
当你在Activity A中点击按钮启动Activity B时,这就像是演员A(当前正在舞台中央)收到了一个指令:让演员B准备上场。
-
演员A的经纪人(
ActivityThread)通过他的接线员(ApplicationThread)这个Binder对讲机,紧急联系总导演(AMS):“导演导演,这里想启动演员B!”
🎬 第二幕:总导演(AMS)的调度
-
总导演(AMS) 接到电话后,立刻翻看他的全局演员表(ActivityStack),并进行一系列调度:
-
•
记录在案:为演员B创建一个新的档案袋(
ActivityRecord)。 -
•
检查场地:决定演员B应该在哪个舞台(Task)上表演,是沿用当前的舞台还是开辟一个新的。
-
•
沟通舞台监督:通知舞台监督(WMS):“注意,一会儿要有新窗口(Window)上来,灯光和焦点准备调整!”
-
•
下达暂停指令:最重要的第一步是,导演通过对讲机告诉经纪人A的接线员:“先让演员A暂停表演!”(
schedulePauseActivity) 。
-
📞 第三幕:经纪人(ActivityThread)安排工作
-
经纪人A的接线员(
ApplicationThread)接到导演的“暂停”电话后,经纪人(ActivityThread)并不会立刻直接告诉演员A。他会把“让演员A执行onPause”这个任务写进自己的日程表(主线程消息队列,Handler H) 里排队,等待执行 。 -
轮到执行这个任务时,经纪人会通过一位助手(
Instrumentation)正式通知演员A:“导演让你做暂停动作了”。于是,演员A开始执行onPause()方法 。
🔄 第四幕:闭环反馈与新一轮调度
-
演员A的
onPause()表演一完成,经纪人A立刻通过对讲机反向通知总导演AMS:“报告导演,演员A已暂停!” -
总导演(AMS) 收到这个反馈信号后,确认了第一步已完成。于是开始第二步调度,再次通过对讲机呼叫演员B所在应用的接线员(如果进程不存在,AMS会先联系Zygote孵化一个新进程和新经纪人):“现在准备启动演员B,这是他的剧本(Intent)和之前保存的状态(Bundle)!”(
scheduleLaunchActivity) 。
🎪 第五幕:新演员的登场与就位(生命周期执行)
-
演员B的经纪人(
ActivityThread)收到导演的“启动”指令后,同样地将“启动演员B”这个任务放入日程表排队。 -
任务执行时,经纪人会:
-
•
找演员:通过反射找到演员B,并把他请到后台(
newActivity)。 -
•
给剧本:为演员B搭建基本的化妆间和道具间(创建
ContextImpl,调用activity.attach())。 -
•
初次彩排:助手(
Instrumentation)通知演员B:“这是你的初始剧本,请开始你的第一次彩排(onCreate)!”——演员B开始执行onCreate(),加载UI布局 。 -
•
登台准备:助手继续通知:“请到侧台准备(
onStart)!”——演员B执行onStart(),此时观众可能还看不到他。 -
•
请求焦点:经纪人同时联系舞台监督(WMS):“我们演员B的舞台布景(View树)好了,请给他打灯光、分配一个Surface(画布)!”
-
-
舞台监督(WMS) 为演员B的窗口安排好位置、层级,并准备好画布(
Surface)。一切就绪后,通知经纪人。 -
经纪人最后通知演员B:“现在,请走到舞台中央,开始你的表演吧!(
onResume)”——演员B执行onResume(),完全进入前台,获得焦点,正式与观众交互 。
📋 生命周期调用顺序总结
| 场景 | 生命周期调用顺序 |
|---|---|
| 正常启动新Activity | onPause(A)-> onCreate(B)-> onStart(B)-> onResume(B)-> onStop(A)(如果A完全不可见) |
| 返回上一个Activity | onPause(B)-> onRestart(A)-> onStart(A)-> onResume(A)-> onStop(B)-> onDestroy(B)(如果B被 finish) |
| 配置变化(如旋转) | onPause-> onSaveInstanceState-> onStop-> onDestroy-> onCreate-> onStart-> onRestoreInstanceState-> onResume |
💡 核心要点
-
•
感知靠指挥:AMS并不是“感知”到生命周期的变化,而是作为总导演,主动发起和调度所有这些生命周期方法的调用。它通过Binder IPC机制向应用进程发送指令 。
-
•
执行在本地:生命周期方法的具体执行,发生在你的应用进程的主线程中,由
ActivityThread和Instrumentation根据AMS的指令来调用 。这就是为什么在生命周期方法里做耗时操作会卡顿甚至ANR。 -
•
协作是关键:WMS(舞台监督) 负责管理窗口、Surface和焦点,与AMS(总导演) 紧密配合。AMS决定“谁该上场”,WMS则负责“如何把上场演员的窗口展示好” 。
-
•
消息队列是核心:从AMS发来的指令是通过Binder线程收到的,但最终都被发送到主线程的消息队列(Message Queue) 中,由Handler H逐个处理,从而保证了所有生命周期方法都在主线程中顺序执行 。
希望这场“舞台剧”能帮助你直观地理解AMS和WMS是如何协同工作,指挥Activity生命周期的。