忽然有一天,我想要做一件事:去代码中去验证那些曾经被"灌输"的理论。
-- 服装学院的IT男
在整个启动流程中,上一篇介绍了第一阶段:SourceActivity 的 onPause
现在分析第二阶段:TargetActivity 启动后会依次执行 onCreate,onStart,onResume。
另外还会完整的介绍一下 Activity 生命周期的事务是如何触发的。
由于篇幅原因,分为以下2篇:
Activity生命周期之onCreate,onStart,onResume-1
Activity生命周期之onCreate,onStart,onResume-2
1. 启动流程介绍
我们知道 onCreate 这个生命周期表示 Activity 的创建,对应 LaunchActivityItem 这个事务,源码中构建这个事务唯一的地方就在 ActivityTaskSupervisor::realStartActivityLocked 方法。
而 ActivityTaskSupervisor::realStartActivityLocked 方法的执行逻辑,在Activity启动流程系列说过要启动 TargetActivity 有2个必要条件:
-
- TargetActivity 所在的应用进程已经启动
-
- SourceActivity 需要执行 onPause
不考虑异常情况,能执行 onCreate 的场景就是冷热启动了,冷热启动区别也就在于多了个需要创建应用进程,不过最终都会执行到 ActivityTaskSupervisor::realStartActivityLocked 方法。
无论是启动进程后执行过来的,还是上篇提到的 SourceActivity 执行 activityPaused 流程触发过来的结果都是一样的,不必太在意
开始撸代码
scss
# ActivityTaskSupervisor
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
// 1. 判断是否执行完了pause 。 也就是2个条件之一,必须要执行完pause才可以进入后面
if (!mRootWindowContainer.allPausedActivitiesComplete()) {
// While there are activities pausing we skipping starting any new activities until
// pauses are complete. NOTE: that we also do this for activities that are starting in
// the paused state because they will first be resumed then paused on the client side.
// 不满足添加就打log
ProtoLog.v(WM_DEBUG_STATES,
"realStartActivityLocked: Skipping start of r=%s some activities pausing...",
r);
return false;
}
......
// 2. wm_restart_activity
EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
task.mTaskId, r.shortComponentName);
// 3.重点* 创建Activity启动事务.将构建的 LaunchActivityItem 添加到 clientTransaction 中
final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.token);
......
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
results, newIntents, r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
// 4.重点*. 设置预期的最终状态Resume逻辑,启动走的这。 表示需要执行到onCreate
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
} else {
// Pause 逻辑
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// 5.重点* 调度事务,将clientTransaction添加到生命周期管理器中
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}
-
- 如果有Activity没有执行完 pause ,则不能执行新的Activity的启动。 如果不满足条件也会相应的ProtoLog
-
- 打印Events日志,格式为:wm_restart_activity: [0,253598020,21,com.google.android.dialer/.extensions.GoogleDialtactsActivity]
-
- 构建 LaunchActivityItem 事务,将会触发创建Activity,并执行到 onCreate
-
- 构建 ResumeActivityItem 事务,将会触发执行到Activity的 onResume
-
- 执行事务
后面的流程其实可以直接去看应用端这2个事务的执行,不过我对这中间的调用比较好奇,所以把生命周期跨进程调用事务的逻辑也梳理了一遍。对这块比较了解的可以跳过,直接看第三章生命周期相关的内容
2. Activity 生命周期事务跨进程处理方式详解
2.1 了解ClientTransaction
在 ActivityTaskSupervisor::realStartActivityLocked 方法中对跨进程执行生命周期事务的代码可以归纳为以下几步:
-
- 构建出 ClientTransaction
-
- 构建 onCreate 和 onResume对应的2个事务,并保存到 ClientTransaction 中
-
- 通过 ClientLifecycleManager::scheduleTransaction 方法来触发事务的调度执行,唯一参数就是 ClientTransaction
这一小节先来了解一下这个 ClientTransaction 到底是什么
csharp
# ClientTransaction
// 实现Parcelable接口,说明可序列化
public class ClientTransaction implements Parcelable, ObjectPoolItem {
// 几个重要的成员变量
private List<ClientTransactionItem> mActivityCallbacks;
private ActivityLifecycleItem mLifecycleStateRequest;
// 目标进程
private IApplicationThread mClient;
// 目标Activity
private IBinder mActivityToken;
// client :对应进程
// activityToken :创建ActivityRecord时的匿名token
public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);
if (instance == null) {
instance = new ClientTransaction();
}
instance.mClient = client;
instance.mActivityToken = activityToken;
return instance;
}
// 拿到对应
public IBinder getActivityToken() {
return mActivityToken;
}
public void addCallback(ClientTransactionItem activityCallback) {
if (mActivityCallbacks == null) {
mActivityCallbacks = new ArrayList<>();
}
// 事务添加到 mActivityCallbacks 列表中
mActivityCallbacks.add(activityCallback);
}
// 事务赋值给 mLifecycleStateRequest 变量
public void setLifecycleStateRequest(ActivityLifecycleItem stateRequest) {
mLifecycleStateRequest = stateRequest;
}
// 目标进程执行事务
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
}
ClientTransaction 的核心方法就这些,结合 ActivityTaskSupervisor::realStartActivityLocked 方法的使用得出以下结论:
-
- ClientTransaction::obtain 构建出一个 ClientTransaction 对象,2个参数分别为目标进程,和目标Activity
-
- addCallback 方法会将 LaunchActivityItem 放到 内部的 mActivityCallbacks 列表中
-
- setLifecycleStateRequest 方法将 ResumeActivityItem 事务赋值给了 mLifecycleStateRequest 变量。
这里还有个重要的方法 schedule() ,最终会触发目标进程执行当前这个 ClientTransaction 。
2.2 事务的调度执行
上一小节知道生命周期的事务都被包装在了一个 ClientTransaction 对象中,现在来看看 ClientLifecycleManager::scheduleTransaction 方法是如何触发对应事务执行的。
该方法有多个重载,但是本质都一样
less
# ClientLifecycleManager
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
// 重点* 调用ClientTransaction::schedule
transaction.schedule();
......
}
void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
@NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
// 构建 一个 ClientTransaction,调用上面的scheduleTransaction
final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
stateRequest);
scheduleTransaction(clientTransaction);
}
......忽略另外几个重载, 都是内部构建出一个 ClientTransaction
主要就是执行了 ClientTransaction::schedule 方法。
2.3 应用进程处理
ClientTransaction::schedule 方法会跨进程调用到目标进程的 scheduleTransaction 方法,我们知道进程指的就是 ActivityThread 内部类 ApplicationThread
csharp
# ActivityThread$ApplicationThread
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
// 这里调用的是ActivityThread的父类 ClientTransactionHandler
ActivityThread.this.scheduleTransaction(transaction);
}
# ClientTransactionHandler
void scheduleTransaction(ClientTransaction transaction) {
// 执行 preExecute (预执行)
transaction.preExecute(this);
// 重点* 发送消息
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
先执行 preExecute 方法,最重要的是执行发送了一个 EXECUTE_TRANSACTION 消息,并把 ClientTransaction 传过去了。
这个消息的处理在 ActivityThread 中。
scala
# ActivityThread
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
class H extends Handler {
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
......
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
// 处理
mTransactionExecutor.execute(transaction);
......
break;
......
}
}
}
ClientTransaction 又被传递到 TransactionExecutor 中处理了。
scss
# TransactionExecutor
public void execute(ClientTransaction transaction) {
......
// LaunchActivityItem
executeCallbacks(transaction);
// ResumeActivityItem
executeLifecycleState(transaction);
......
}
2.3.1 executeCallbacks 和 executeLifecycleState 方法
为什么我在上面注释里说 executeCallbacks 是处理 LaunchActivityItem,executeLifecycleState 是处理 ResumeActivityItem 呢? 代码中有答案:
java
# TransactionExecutor
public void executeCallbacks(ClientTransaction transaction) {
// 获取 callback 的元素,没有就返回
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
if (callbacks == null || callbacks.isEmpty()) {
// No callbacks to execute, return early.
return;
}
......
// 当前场景是触发 LaunchActivityItem的execute方法
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
......
}
private void executeLifecycleState(ClientTransaction transaction) {
// 获取tLifecycleStateRequest,没有就返回
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
......
// 重点* 将Activity的状态转换至接近最终目标状态的位置 也就是会触发onStart
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
// Execute the final transition with proper parameters.
// 当前场景是触发LaunchActivityItem的execute
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
而之前SystemService对这2个事务的处理如下:
lua
ActivityTaskSupervisor::realStartActivityLocked
LaunchActivityItem.obtain -- 添加到事务到 mActivityCallbacks 列表
ResumeActivityItem.obtain -- 设置事务到 mLifecycleStateRequest
ClientLifecycleManager::scheduleTransaction -- 触发事务的执行
所以说:executeCallbacks 方法是处理 LaunchActivityItem,executeLifecycleState 是处理 ResumeActivityItem。
2.4 小结
经过上面这些分析,我们知道在 ActivityTaskSupervisor::realStartActivityLocked 方法中启动 Activity 就是构建了2个事务到 ClientTransaction 中,并跨进程到目标进程执行。
2个事务从SystemService进程到目标应用进程完整的调用链如下:
php
ActivityTaskSupervisor::realStartActivityLocked
ClientTransaction::obtain -- 构建客户端事务
LaunchActivityItem::obtain -- 构建 onCreate 启动事务
ClientTransaction::addCallback -- onCreate事务添加进回调
ResumeActivityItem::obtain -- 构建 onResume 事务
ClientTransaction::setLifecycleStateRequest -- onResume 事务添加进LifecycleStateRequest
ClientLifecycleManager::scheduleTransaction -- 执行事务
ClientTransaction::schedule -- 触发目标进程执行
ActivityThread$ApplicationThread::scheduleTransaction -- 进入应用进程
ClientTransactionHandler::scheduleTransaction
ClientTransaction::preExecute
ActivityThread::sendMessage -- 发送"EXECUTE_TRANSACTION"消息
ActivityThread$H::handleMessage
TransactionExecutor::execute
TransactionExecutor::executeCallbacks -- LaunchActivityItem 事务
LaunchActivityItem::execute -- 触发 onCreate
LaunchActivityItem::postExecute
TransactionExecutor::executeLifecycleState -- ResumeActivityItem 事务
TransactionExecutor::cycleToPath -- 触发 onStart
ResumeActivityItem::execute -- 触发 onResume
ResumeActivityItem::postExecute
时序图如下:
可以看到从 生命周期事务的执行到真正触发其 execute 方法,中间的调用链还是很长的,不过这个流程也不算很重要,一般看到 ResumeActivityItem 这种事务构建了,直接去看对应的 execute,postExecute 等方法就好了。
从调用链上也看到了 3个生命周期的执行顺序和期望的log打印也是一样的,当然具体是怎么执行到的要看后续代码分析。
3. 总结
这一篇对介绍了 Activity 启动流程中 SystemService 端末尾的工作, 另外介绍了一下 Activity 生命周期事务跨进程处理方式,关于onCreate,onStart,onResume 这3个生命周期在SystemService 端的流程介绍完了,下一篇是重点,会详细介绍在应用端对这3个生命周期的处理流程。