Activity事务管理讲解(ClientLifecycleManager)

发布时间:2025-09-27 01:05

'任务清单制作与管理'技巧讲解视频 #生活常识# #时间管理建议# #时间管理视频教程#

前言:

安卓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)) {

transaction.recycle();

}

}

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:

@Override

public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {

ActivityThread.this.scheduleTransaction(transaction);

}

void scheduleTransaction(ClientTransaction transaction) {

transaction.preExecute(this);

sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);

}

case EXECUTE_TRANSACTION:

final ClientTransaction transaction = (ClientTransaction) msg.obj;

mTransactionExecutor.execute(transaction);

if (isSystem()) {

transaction.recycle();

}

break

public void execute(ClientTransaction transaction) {

...

executeCallbacks(transaction);

executeLifecycleState(transaction);

mPendingActions.clear();

}

item.execute(mTransactionHandler, token, mPendingActions);

item.postExecute(mTransactionHandler, token, mPendingActions);

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:

public class ResumeActivityItem extends ActivityLifecycleItem {

public void execute(ClientTransactionHandler client, ActivityClientRecord r,

PendingTransactionActions pendingActions) {

client.handleResumeActivity(r, true , mIsForward,

"RESUME_ACTIVITY");

}

@Override

public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,

boolean isForward, String reason) {

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);

}

void scheduleTransaction(ClientTransaction transaction) {

transaction.preExecute(this);

sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);

}

case EXECUTE_TRANSACTION:

final ClientTransaction transaction = (ClientTransaction) msg.obj;

mTransactionExecutor.execute(transaction);

if (isSystem()) {

transaction.recycle();

}

break

public void execute(ClientTransaction transaction) {

...

executeCallbacks(transaction);

executeLifecycleState(transaction);

mPendingActions.clear();

}

item.execute(mTransactionHandler, token, mPendingActions);

item.postExecute(mTransactionHandler, token, mPendingActions);

private void executeLifecycleState(ClientTransaction transaction) {

...

cycleToPath(r, lifecycleItem.getTargetState(), true , transaction);

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来说,一次就可以明确所有将要被执行到的事务。

网址:Activity事务管理讲解(ClientLifecycleManager) https://www.yuejiaxmz.com/news/view/1338732

相关内容

Android项目中Activity生命周期高效的管理方式
Activity以各种方式启动Activity、状态保存,完全退出等
安卓笔记之隐式启动Activity篇
spring事务管理(详解和实例)
Spring Boot校园活动管理系统:打造数字化校园生活新体验
RESEARCH FRAMEWORK OF SUBURBAN SPACE BASED ON PERSPECTIVE OF LIVING SPACE AND ACTIVITY SPACE
服务管理模块专题之一压力与情绪管理讲解.ppt
A cohort study on the impact of stressful life events on social activity participation among middle
时间与压力管理 (企顾司面授学习)
activity启动时的启动窗口(starting window)? 如何修改启动窗口的背景色?

随便看看