Android 生命周期函数调用原理
工作原理详解
1. 消息的源头:系统服务(通过 Binder 线程)
- 当 AMS 决定要回调一个生命周期方法(如
onCreate
)时,它并不会直接调用你的 Activity 方法 - 它会通过 Binder IPC,向你的应用进程发送一个指令。这个指令最终会调用到
ActivityThread
的内部类ApplicationThread
的对应方法(如scheduleLaunchActivity
)
2. 消息的封装和投递(ApplicationThread -> H)
ApplicationThread
的方法运行在 Binder 线程池中的某个线程上,而不是主线程- 为了切换到主线程执行,这些方法会做一件事:将客户端(如 AMS)的请求封装成一个
Message
,然后发送给主线程的Handler
- 这个
Handler
就是ActivityThread
中的内部类H
(继承自Handler
) - 例如,在
scheduleLaunchActivity
中:// 这运行在Binder线程 public final void scheduleLaunchActivity(...) {...// 1. 封装信息ActivityClientRecord r = new ActivityClientRecord(...);// 2. 发送消息到主线程队列sendMessage(H.LAUNCH_ACTIVITY, r); }
sendMessage
方法最终会调用H
的sendMessage
方法,将H.LAUNCH_ACTIVITY
这个消息和包含所有数据的ActivityClientRecord
对象放入主线程的MessageQueue
中
3. 消息的处理(H 在主线程处理)
- 主线程的
Looper
一直在无限循环Looper.loop()
,不断地从MessageQueue
中取出Message
- 取出的
Message
会分发给它的目标Handler
,也就是H
来处理 H
的handleMessage(Message msg)
方法是一个巨大的switch
语句,根据msg.what
(即消息类型,如LAUNCH_ACTIVITY
,RESUME_ACTIVITY
,PAUSE_ACTIVITY
)来执行不同的操作class H extends Handler {public static final int LAUNCH_ACTIVITY = 100;public static final int RESUME_ACTIVITY = 107;public static final int PAUSE_ACTIVITY = 101;// ... 很多其他消息类型public void handleMessage(Message msg) {switch (msg.what) {case LAUNCH_ACTIVITY:handleLaunchActivity((ActivityClientRecord) msg.obj, ...);break;case RESUME_ACTIVITY:handleResumeActivity((ActivityClientRecord) msg.obj, ...);break;case PAUSE_ACTIVITY:handlePauseActivity((ActivityClientRecord) msg.obj, ...);break;// ... 处理其他消息}} }
4. 最终回调到 Activity
- 在
H
的handleLaunchActivity
,handleResumeActivity
等方法中,会执行一系列复杂的逻辑,但最终都会直接调用到 Activity 的对应生命周期方法 - 例如,在
handleLaunchActivity
中:private void handleLaunchActivity(ActivityClientRecord r, ...) {...// 1. performLaunchActivity 会完成Activity对象的创建、Context的绑定、Application的attach等Activity activity = performLaunchActivity(r, customIntent);...if (activity != null) {...// 2. 紧接着调用 handleResumeActivityhandleResumeActivity(...);} }private void handleResumeActivity(...) {...// 最终会调用到 Activity 的 onResume 方法performResumeActivity(...); }// performResumeActivity 内部简化逻辑: final Instrumentation.ActivityResult result = activity.performResume(); // activity.performResume() 内部会调用: // mInstrumentation.callActivityOnResume(this); // 而 callActivityOnResume 内部就是直接调用: // activity.onResume();
画面绘制(View Drawing)也是如此
画面绘制的请求同样是通过消息机制驱动的:
- 触发绘制: 当 Activity 变为可见、View 内容发生变化(如
setText()
)、或用户触摸屏幕时,ViewRootImpl
会请求安排一次绘制流程 - 发送消息:
ViewRootImpl.scheduleTraversals()
会向主线程的MessageQueue
提交一个异步消息(通常是一个Runnable
任务,类型为TraversalRunnable
) - 处理消息: 主线程的
Looper
取出这个任务并执行 - 执行绘制: 在这个
Runnable
的run()
方法中,会调用doTraversal()
,继而执行著名的“View 绘制三部曲”:measure()
,layout()
,draw()
。这一切都发生在主线程上
总结
系统回调类型 | 消息来源 (Binder调用) | 对应的 H 消息类型 | 最终处理的方法 |
---|---|---|---|
Activity 生命周期 | ApplicationThread.scheduleXxxActivity() | LAUNCH_ACTIVITY , RESUME_ACTIVITY , PAUSE_ACTIVITY 等 | Activity.onCreate() , onResume() , onPause() 等 |
Service 生命周期 | ApplicationThread.scheduleXxxService() | CREATE_SERVICE , BIND_SERVICE , SERVICE_ARGS 等 | Service.onCreate() , onBind() , onStartCommand() 等 |
广播接收 (Broadcast) | ApplicationThread.scheduleReceiver() | RECEIVER | BroadcastReceiver.onReceive() |
画面绘制 (UI Update) | ViewRootImpl.scheduleTraversals() | (通常是一个 Runnable 任务) | View.measure() , layout() , draw() |
因此,主线程的 Looper
和 Handler
(H
) 是整个应用进程的“心脏”和“中枢神经系统”。所有来自系统或其他线程的事件,都被转化为消息,由它按顺序、串行地分发给正确的组件进行处理,从而保证了线程安全。这也是为什么不能在主线程执行耗时操作的原因——它会阻塞消息队列,导致生命周期回调、界面绘制等所有消息都无法被及时处理,造成应用卡顿甚至 ANR