前言:
安卓9开始,Activity的启动流程中,不再是系统侧直接通知APP去执行相应的生命周期,而是通过ClientLifecycleManager事务管理来替代,即系统侧构造一些事务对象,一次性传递给APP,由APP完成最终的执行。
初学者会觉得这块逻辑很绕,让人看的云里雾里,但是其实懂了之后,就会发现其实流程上并没有那么的复杂。
本文就以两种最场景的Activity启动方式的流程讲解,带你来一起深入了解一下ClientLifecycleManager的实现原理和流程。
PS:本文代码以安卓13为例讲解。
一.复用Activity的启动流程
如果Activity的启动模式是非standard类型,那么就有可能进入到Activity的复用场景。即系统侧帮我们找到符合Intent中要求的并且已存在的Activity对象,然后把这个Activity对象挪到前台显示,实现对Activity的复用。
1.1 系统侧构造
我们先看一下这种复用类型,系统侧是如何通知APP的。
首先,我们介绍一下系统侧构造过程中使用到的类:
1.1.1 系统侧的重点类介绍
ClientTransaction
ClientTransaction是承载事务的实体类,其实现Parcelable接口的,是可被序列化传输的,这个类的对象也是最终被传递到APP侧的那个。这个类中主要包含四个成员变量:
变量名 | 类型 | 介绍 |
mActivityCallbacks | List<ClientTransactionItem> | 回调集合,回调主要包含两种类型。 第一种,生命周期类型的回调,比如ResumeActivityItem,这种类型都继承自ActivityLifecycleItem类。 第二种,方法回调,比如NewIntentItem/ActivityResultItem,对应回调onNewIntent和onActivityResult方法等。 |
mLifecycleStateRequest | ActivityLifecycleItem | 因为类型是ActivityLifecycleItem,所以只允许赋值为生命周期类型的回调,而且只能有一个。 |
mClient | IApplicationThread | binder引用,对应服务类是APP一侧的ApplicationThread。 |
mActivityToken | IBinder | binder引用,对应APP侧唯一的Activity中的binder服务类。 |
ClientLifecycleManager
事务管理类,也就是本文标题中的那个类。这个类中的核心方法只有一个,即scheduleTransaction方法。
代码1-1:
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
//ClientTransaction中的schedule方法
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
这个方法中,传入ClientTransaction对象,方法中直接调用schedule方法。而schedule中的方法实现其实就是调用binder方法scheduleTransaction,最终这个调用会被ActivityThread.ApplicationThread中的scheduleTransaction方法接收。
1.1.2 系统侧执行流程
当找到满足复用的Activity对象,并且准备复用时,都会调用到TaskFragment类中的resumeTopActivity方法,下面截取该方法中部分核心代码进行讲解:
代码1-2:
//逻辑1,构建ClientTransaction
final ClientTransaction transaction =
ClientTransaction.obtain(next.app.getThread(), next.appToken);
//逻辑2,添加NewIntentItem事务
if (next.newIntents != null) {
transaction.addCallback(
NewIntentItem.obtain(next.newIntents, true /* resume */));
}
//逻辑3,添加生命周期事物
transaction.setLifecycleStateRequest(
ResumeActivityItem.obtain(next.app.getReportedProcState(),
dc.isNextTransitionForward()));
//逻辑4,通知APP一侧
mAtmService.getLifecycleManager().scheduleTransaction(transaction);
-
在系统侧的逻辑中,首先会构建一个ClientTransaction对象,ClientTransaction上一小节有介绍到。
-
我们都知道,复用Activity的情况下,会调用这个被复用的Activity的onNewIntent方法。所以,这里会构造一个NewIntentItem类型的事务对象,添加到会被添加NewIntentItem的事务,这事务对应的就是回调Activity的onNewIntent方法,这里会添加到ClientTransaction的mActivityCallbacks集合中。
-
添加生命周期resume的事务,这个事务对应的就是回调Activity的onResume方法,这里会赋值给ClientTransaction中的成员变量mLifecycleStateRequest。
-
通知APP一侧。通过调用ClientLifecycleManager中的scheduleTransaction方法,最终通知给APP一侧的ActivityThread.ApplicationThread中的scheduleTransaction方法。
1.1.3 mActivityCallbacks和mLifecycleStateRequest的区别
首先,mActivityCallbacks允许任何类型的回调,而mLifecycleStateRequest允许生命周期的回调;
其次,mActivityCallbacks是集合,可以装载多个回调,而mLifecycleStateRequest只能一个;
再次,在APP侧的执行顺序,是优先mActivityCallbacks,而后执行mLifecycleStateRequest。所以mLifecycleStateRequest一般对应的是最后一个被执行到的生命周期方法。
1.2 客户端执行
系统侧发出了通知之后,接下来就是APP侧的接收和处理逻辑了,按照老规矩,我们仍然也先介绍一些APP侧的重点类。
1.2.1 APP侧的重点类介绍
ActivityThread
APP一侧的核心执行类,这个太基础了,就不多介绍了。
ActivityThread.ApplicationThread
APP一侧提供给系统侧的binder服务类,主要负责和系统侧交互通信。
1.2.2 APP侧的执行流程
接下来,我们看一下APP侧收binder调用后,是如何处理的,相关代码经过整理,如下:
代码1-3:
//ActivityThread.ApplicationThread类中scheduleTransaction方法,逻辑1
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
//ClientTransactionHandler类中的scheduleTransaction方法,逻辑2
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
//ActivityThread.H类中的handleMessage方法,截取处理EXECUTE_TRANSACTION消息的逻辑,逻辑3
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break
//TransactionExecutor类中的execute方法,逻辑4
public void execute(ClientTransaction transaction) {
...
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
}
//TransactionExecutor类中的executeCallbacks分代码,逻辑5,下同
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
//TransactionExecutor类中的executeLifecycleState方法部分代码
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
-
我们都知道IApplicationThread在APP侧的服务类就是ActivityThread.ApplicationThread,所以scheduleTransaction方法最终会调用到ApplicationThread中的scheduleTransaction方法,然后转交到ActivityThread中的scheduleTransaction方法进行处理。
-
ActivityThread继承自抽象类ClientTransactionHandler,而scheduleTransaction方法正是由这个抽象类提供。首先进行执行前回调,回调方法preExecute,然后切换到主线程继续处理。
-
主线程中,使用TransactionExecutor类调用其execute方法。
-
execute方法中,核心其实就是执行两种回调,分别是callbacks集合和lifecycleItem事务,也就是我们上面讲的支线任务和主线任务。
-
两种不同的事物对象,最终执行的逻辑是一样的,都是先执行execute方法,然后在执行完成回调postExecute。
接下来,我们分别了解一下两种不同的事物对象,是如何完成方法回调的。
1.2.3 NewIntentItem类型的执行流程
首先,看一下NewIntentItem类的相关逻辑,相关代码整理如下:
代码1-4:
//NewIntentItem类,逻辑1
public class NewIntentItem extends ActivityTransactionItem {
@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
client.handleNewIntent(r, mIntents);
}
}
//ActivityThread类中handleNewIntent方法,逻辑2
@Override
public void handleNewIntent(ActivityClientRecord r, List<ReferrerIntent> intents) {
checkAndBlockForNetworkAccess();
deliverNewIntents(r, intents);
}
//ActivityThread类中deliverNewIntents方法,逻辑3
private void deliverNewIntents(ActivityClientRecord r, List<ReferrerIntent> intents) {
final int N = intents.size();
for (int i=0; i<N; i++) {
ReferrerIntent intent = intents.get(i);
intent.setExtrasClassLoader(r.activity.getClassLoader());
intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
r.activity.getAttributionSource());
r.activity.mFragments.noteStateNotSaved();
mInstrumentation.callActivityOnNewIntent(r.activity, intent);
}
}
-
execute中会调用handleNewIntent方法;
-
这里的client其实就是ActivityThread对象,所以最终会调用到ActivityThread的handleNewIntent方法,而后又会调用到deliverNewIntents方法。
-
deliverNewIntents方法中,通过Instrumentation完成真正的调用,调用到Activity的onNewIntent对象。
1.2.4 ResumeActivityItem类型的执行流程
再来看一下ResumeActivityItem的类型,相关代码整理如下:
代码1-5:
//ResumeActivityItem的execute方法,逻辑1
public class ResumeActivityItem extends ActivityLifecycleItem {
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
"RESUME_ACTIVITY");
}
//ActivityThread类中的handleResumeActivity方法,逻辑2
@Override
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
boolean isForward, String reason) {
//回调onResume方法以及一下其它操作,逻辑3
if (!performResumeActivity(r, finalStateRequest, reason)) {
return;
}
...关联window等等逻辑,这里就不扩展了
}
-
execute方法中会调用到ClientTransactionHandler的handleResumeActivity方法。
-
这里的ClientTransactionHandler其实就是ActivityThread,所以会调用到ActivityThread中的handleResumeActivity方法。
-
handleResumeActivity方法中,会首先回调生命周期,然后执行Activity关联window等逻辑,这里就不扩展讲了。
二.新建Activity的启动流程
这一章,我们仍然分成系统侧调用逻辑,以及客户端执行逻辑来讲。
2.1 系统侧逻辑
2.1.1 前置条件
如果不存在满足复用的Activity,或者Activity的启动模式设定不需要复用,那么就会新生成一个Activity对象。此时系统已经把Activity在系统侧的对象ActivityRecord都已经创建和配置好了,哪怕是跨进程/应用启动,系统也会先把相关的进程创建好之后在执行启动Activity的流程。而App收到通知后,需要完成创建,启动,关联等流程。
2.1.2 系统侧执行流程
启动一个新的Activity的方法,在ActivityTaskSupervisor的realStartActivityLocked方法中,相关代码整理如下:
代码2-1:
//创建ClientTransaction对象,逻辑1
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.token);
//逻辑2
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),...)
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
} else {
lifecycleItem = PauseActivityItem.obtain();
}
//逻辑3
clientTransaction.setLifecycleStateRequest(lifecycleItem);
//逻辑4
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
-
首先仍然会构建一个ClientTransaction对象。
-
一个新的Activity被创建,那么是需要执行onCreate方法的,其对应的事务对象为LaunchActivityItem。所以这里添加一个回调对象,并且还把启动参数配置对象intent添加到LaunchActivityItem中,供给APP启动时使用。
-
添加生命周期resume的事务对象,这个事务对应的就是回调Activity的onResume方法,这里会赋值给ClientTransaction中的成员变量mLifecycleStateRequest。
-
通知APP一侧。通过调用ClientLifecycleManager中的scheduleTransaction方法,最终通知给APP一侧的ActivityThread.ApplicationThread中的scheduleTransaction方法。
和第一章中介绍的复用Activity的启动流程中做对比,这里添加添加了两个生命周期的事务,分别是onCreate和onResume。但是我们都知道,一个Activity启动的完成流程应该是onCreate/onStart/onResume才对,别急,接下来我们看一下APP侧的逻辑,就知道原因了。
2.2 APP侧逻辑
2.2.1 APP侧的执行流程
前面的执行流程和第一章中复用的场景是一样的。
代码2-2:
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
//ClientTransactionHandler类中的scheduleTransaction方法,
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
//ActivityThread.H类中的handleMessage方法,截取处理EXECUTE_TRANSACTION消息的逻辑
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break
//TransactionExecutor类中的execute方法
public void execute(ClientTransaction transaction) {
...
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
}
//TransactionExecutor类中的executeCallbacks分代码,逻辑2
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
//TransactionExecutor类中的executeLifecycleState方法部分代码
private void executeLifecycleState(ClientTransaction transaction) {
...
//流程4
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
//流程3
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
-
前面的流程中,和复用Activity的逻辑是一致的,所以这里就不重复再讲了。
-
executeCallbacks方法中,因为传入的是LaunchActivityItem,所以最后会调用到Activity的onCreate流程,这个我们2.2.2小节来讲。
-
executeLifecycleState方法中,lifecycleItem为ResumeActivityItem,所以这里最终会调用到Activity的onResume流程。这个和第一章的流程是一样的,所以这里就不介绍了。
-
其实流程3之前,还有一个cycleToPath方法,这也是调用onStart方法的原因所在,这个我们2.2.3小节来讲。
2.2.2 LaunchActivityItem类型的执行流程
再来看一下LaunchActivityItem的类型,相关代码整理如下:
代码2-3:
//LaunchActivityItem的execute方法,逻辑1
public class LaunchActivityItem extends ActivityLifecycleItem {
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
mTaskFragmentToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}
}
//ActivityThread类中的handleLaunchActivity方法,逻辑2
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
//调用performLaunchActivity方法,逻辑3
final Activity a = performLaunchActivity(r, customIntent)
...
}
//ActivityThread类中的performLaunchActivity方法,逻辑4
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
//生成ContextImpl委托对象,这里的ContextImpl和Application中的ContextImpl可不是一个,逻辑5
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//通过反射生成Activity对象,逻辑6
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
appContext.getAttributionSource());
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e){
...
}
//Activity进行关联,这时候会把自身的状态同步到系统侧,流程7
activity.attach(...);
//绑定主题,流程8
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
//执行onCreate生命周期,流程9
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
-
execute方法中首先会构造一个客户端的ActivityClientRecord对象,这个对象和服务端的ActivityRecord一一对应,是APP侧的Activity的记录对象,然后调用ClientTransactionHandler的handleLaunchActivity方法。
-
这里的ClientTransactionHandler其实就是ActivityThread,所以会调用到ActivityThread中的handleLaunchActivity方法。
-
handleResumeActivity方法中,调用performLaunchActivity方法。
-
performLaunchActivity负责创建和启动Activity,这个流程中包含多个功能,我们一一来讲。
-
首先,会生成一个委托对象ContextImpl,这个对象存在于ContextWapper中,负责除了activity启动之外几乎其它所有的事务。
-
通过反射生成Activity对象,这里是通过反射去生成的,这也就是为什么我们所说,Activity的构造方法不能有参数的原因。
-
通过attach方法进行关联,此时会做一些成员变量的创建和赋值,比如Window就是此时创建的,但是这时候只是创建,并没有关联到系统侧。
-
绑定Activity的主题。
-
调用Activitiy的生命周期方法onCreate。
2.2.3 onStart生命周期方法的调用原理
之前我们有讲到,系统传递过来的时候并没有StartActivityItem的类型,那么这个流程从何而来呢?
我们详细看一下executeLifecycleState中的cycleToPath方法
代码2-4:
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
ClientTransaction transaction) {
final int start = r.getLifecycleState();
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Cycle activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " from: " + getStateName(start) + " to: " + getStateName(finish)
+ " excludeLastState: " + excludeLastState);
}
final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
performLifecycleSequence(r, path, transaction);
}
首先,这里会有两个状态,start和finish,分别代表开始和完成时的生命周期状态,那么此时的start对应的生命周期状态就是create,因为刚刚create完成,resume还未执行。而finish对应的生命周期状态就是resume,因为系统侧传过来的生命周期事务就是ResumeActivityItem。
然后通过getLifecyclePath方法获取start和finish之间的生命周期方法,相关代码如下:
代码2-5:
@VisibleForTesting
public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
...
mLifecycleSequence.clear();
if (finish >= start) {
if (start == ON_START && finish == ON_STOP) {
// A case when we from start to stop state soon, we don't need to go
// through the resumed, paused state.
mLifecycleSequence.add(ON_STOP);
} else {
// 添加start到finsih之间的所有状态,不包含start。
for (int i = start + 1; i <= finish; i++) {
mLifecycleSequence.add(i);
}
}
} else { // finish < start, can't just cycle down
...
}
//上面添加的是2和3,这里删掉最后一位的3,就只剩下2了
if (excludeLastState && mLifecycleSequence.size() != 0) {
mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
}
return mLifecycleSequence;
}
我们再来看一下create和resume对应的状态,ON_CREATE和ON_RESUME之间正好差了一个ON_START。
代码2-6:
public static final int PRE_ON_CREATE = 0;
public static final int ON_CREATE = 1;
public static final int ON_START = 2;
public static final int ON_RESUME = 3;
public static final int ON_PAUSE = 4;
public static final int ON_STOP = 5;
public static final int ON_DESTROY = 6;
public static final int ON_RESTART = 7;
也就是说代码8中,返回的IntArray长度为1,只包含Start类型。所以,这时候会调用performLifecycleSequence方法去执行对应的生命周期,比如这里执行的就是ON_START的生命周期,相关代码如下:
代码2-7:
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
ClientTransaction transaction) {
final int size = path.size();
for (int i = 0, state; i < size; i++) {
state = path.get(i);
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
null /* customIntent */);
break;
case ON_START:
//这里调用ActivityThread的handleStartActivity方法去执行相应的生命周期
mTransactionHandler.handleStartActivity(r, mPendingActions,
null /* activityOptions */);
break;
...
}
}
三.总结
小结
Activity的事务管理,其实就是换了一种方式通知APP去执行对应的生命周期方法。
9.0之前的方式,是系统侧判断需要创建Activity了,就通知APP去创建以及执行onCreate方法,然后又判断需要关联了,于是又通知APP去执行onStart以及onResume方法等等,需要多次通知。
而使用了事务管理之后,把所有的事务打包成一个对象,把这个对象传递给APP一侧,让APP自身去完成整个的流程,这样只需要通知一次就可以完成整个流程。
优势
最后,我们总结一下事务管理相对于之前的方式的优点,也就是为什么系统要这么优化的原因。
1.降低传输频次,使用事务后传输一次即可。
2.逻辑收口,我们看系统侧的相关代码,对于APP的周期逻辑都是聚在一起的,清晰明确。
3.对于APP来说,一次就可以明确所有将要被执行到的事务。