Activity事务管理讲解(ClientLifecycleManager)

前言:

安卓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);
  1. 在系统侧的逻辑中,首先会构建一个ClientTransaction对象,ClientTransaction上一小节有介绍到。

  2. 我们都知道,复用Activity的情况下,会调用这个被复用的Activity的onNewIntent方法。所以,这里会构造一个NewIntentItem类型的事务对象,添加到会被添加NewIntentItem的事务,这事务对应的就是回调Activity的onNewIntent方法,这里会添加到ClientTransaction的mActivityCallbacks集合中。

  3. 添加生命周期resume的事务,这个事务对应的就是回调Activity的onResume方法,这里会赋值给ClientTransaction中的成员变量mLifecycleStateRequest。

  4. 通知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);
  1. 我们都知道IApplicationThread在APP侧的服务类就是ActivityThread.ApplicationThread,所以scheduleTransaction方法最终会调用到ApplicationThread中的scheduleTransaction方法,然后转交到ActivityThread中的scheduleTransaction方法进行处理。

  2. ActivityThread继承自抽象类ClientTransactionHandler,而scheduleTransaction方法正是由这个抽象类提供。首先进行执行前回调,回调方法preExecute,然后切换到主线程继续处理。

  3. 主线程中,使用TransactionExecutor类调用其execute方法。

  4. execute方法中,核心其实就是执行两种回调,分别是callbacks集合和lifecycleItem事务,也就是我们上面讲的支线任务和主线任务。

  5. 两种不同的事物对象,最终执行的逻辑是一样的,都是先执行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);
    }
}
  1. execute中会调用handleNewIntent方法;

  2. 这里的client其实就是ActivityThread对象,所以最终会调用到ActivityThread的handleNewIntent方法,而后又会调用到deliverNewIntents方法。

  3. 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等等逻辑,这里就不扩展了
}
  1. execute方法中会调用到ClientTransactionHandler的handleResumeActivity方法。

  2. 这里的ClientTransactionHandler其实就是ActivityThread,所以会调用到ActivityThread中的handleResumeActivity方法。

  3. 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);
  1. 首先仍然会构建一个ClientTransaction对象。

  2. 一个新的Activity被创建,那么是需要执行onCreate方法的,其对应的事务对象为LaunchActivityItem。所以这里添加一个回调对象,并且还把启动参数配置对象intent添加到LaunchActivityItem中,供给APP启动时使用。

  3. 添加生命周期resume的事务对象,这个事务对应的就是回调Activity的onResume方法,这里会赋值给ClientTransaction中的成员变量mLifecycleStateRequest。

  4. 通知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);
}

  1. 前面的流程中,和复用Activity的逻辑是一致的,所以这里就不重复再讲了。

  2. executeCallbacks方法中,因为传入的是LaunchActivityItem,所以最后会调用到Activity的onCreate流程,这个我们2.2.2小节来讲。

  3. executeLifecycleState方法中,lifecycleItem为ResumeActivityItem,所以这里最终会调用到Activity的onResume流程。这个和第一章的流程是一样的,所以这里就不介绍了。

  4. 其实流程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);
    } 
}
  1. execute方法中首先会构造一个客户端的ActivityClientRecord对象,这个对象和服务端的ActivityRecord一一对应,是APP侧的Activity的记录对象,然后调用ClientTransactionHandler的handleLaunchActivity方法。

  2. 这里的ClientTransactionHandler其实就是ActivityThread,所以会调用到ActivityThread中的handleLaunchActivity方法。

  3. handleResumeActivity方法中,调用performLaunchActivity方法。

  4. performLaunchActivity负责创建和启动Activity,这个流程中包含多个功能,我们一一来讲。

  5. 首先,会生成一个委托对象ContextImpl,这个对象存在于ContextWapper中,负责除了activity启动之外几乎其它所有的事务。

  6. 通过反射生成Activity对象,这里是通过反射去生成的,这也就是为什么我们所说,Activity的构造方法不能有参数的原因。

  7. 通过attach方法进行关联,此时会做一些成员变量的创建和赋值,比如Window就是此时创建的,但是这时候只是创建,并没有关联到系统侧。

  8. 绑定Activity的主题。

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失落夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值