Activity深入之启动流程

Activity深入之启动流程
Activity作为四大组件之一,一般我们在日常开发中通过以下方式拉起Activity。
Intent intent = new Intent(this,NextActivity.class);
startActivity(intent);
那么startActivity之后的流程是怎样的呢?接下来我们通过流程图加源码的方式走入底层看一看。下图是应用层视角一次完整的Activity启动流程图。


image.png

预览目录
1、Context.startActivity
2、Instrumentation.execStartActivity()
3、ActivityTaskManagerService.startActivity
4、ActivityStarter.execute
5、ActivityRecord.resumeTopActivityUncheckedLocked
6、ActivityRecord.resumeTopActivityUncheckedLocked
7、ApplicationThread.scheduleTransaction
8、ApplicationThread.performLaunchActivity

提前声明本文源码阅读基于Android11。与早些的Android版本存在一定程度的偏差。
1、Context.startActivity
startActivity调用的是Context的startActivity。而Context只是接口类,具体的实现在ContextImpl中。

@Override
public void startActivity(Intent intent, Bundle options) {
    warnIfCallingFromSystemProcess();

    // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
    // generally not allowed, except if the caller specifies the task id the activity should
    // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
    // maintain this for backwards compatibility.
    final int targetSdkVersion = getApplicationInfo().targetSdkVersion;

    if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
            && (targetSdkVersion < Build.VERSION_CODES.N
                    || targetSdkVersion >= Build.VERSION_CODES.P)
            && (options == null
                    || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
        throw new AndroidRuntimeException(
                "Calling startActivity() from outside of an Activity "
                        + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                        + " Is this really what you want?");
    }
    mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity) null, intent, -1, options);
}

该方法里仅做了启动标志位的校验,若不满足则抛出异常。这个异常就是在非Activity场景下拉起抛出的异常。说的就是在非Activity场景下拉起时需要指定Intent.FLAG_ACTIVITY_NEW_TASK标志位,即在新的任务栈中创建Activity。而在Activity中拉起Activity时则会加入到已有的任务栈中。
另外一个启动入口则在Activity中。Activity类重写了startActivity,紧接着走到startActivityForResult,在该方法中也是调用的Instrumentation.execStartActivity()。

2、Instrumentation.execStartActivity()
接着看一下Instrumentation.execStartActivity(),如下所示:

public ActivityResult execStartActivity(
    Context who, IBinder contextThread, IBinder token, String target,
    Intent intenrt, int requestCode, Bundle options) {
        IApplicationThead whoThread = (IApplicationThread) contextThread;
    ...
try {
        intent.migrateExtraStreamToClipData(who);
        intent.prepareToLeaveProcess(who);
        int result = ActivityTaskManager.getService().startActivity(whoThread,
                who.getBasePackageName(), who.getAttributionTag(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()), token, target,
                requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

从以上代码可以看出,实际的启动Activity是在ActivityTaskManager.getService().startActivity。通过查看getService的代码,它获取了IActivityTaskManager的单实例,Singleton是一个单例的封装类,第一次调用它的get方法则会通过create方法来初始化IActivityTaskManager这个对象。IActivityTaskManager是一个binder接口,具体的实现是在ActivityTaskManagerService
此时Activity的启动转到了ActivityTaskManagerService。与此同时这里还把 App 中 Binder 的 Server 端的 ApplicationThread 的句柄传给 ATMS,用于生命周期的回调等,如 onPause。

/** @hide */
public static IActivityTaskManager getService() {
    return IActivityTaskManagerSingleton.get();
}

@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
        new Singleton<IActivityTaskManager>() {
            @Override
            protected IActivityTaskManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                return IActivityTaskManager.Stub.asInterface(b);
            }
        };

3、ActivityTaskManagerService.startActivity
startActivity有几个同名不同参的函数,最后都调用到startActivityAsUser。这里需要说一下,ActivityManagerService中也有startActivity的入口,但其实最终的走向都是到达以下方法。

private int startActivityAsUser(IApplicationThread caller, String callingPackage,
        @Nullable String callingFeatureId, Intent intent, String resolvedType,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
    assertPackageMatchesCallingUid(callingPackage);
    enforceNotIsolatedCaller("startActivityAsUser");

    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    // TODO: Switch to user app stacks here.
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setCallingFeatureId(callingFeatureId)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setUserId(userId)
            .execute();
}

ActivityStartController的主要作用就是接收Activity请求并为此做准备提供给ActivityStarter。该类则收集了一系列Activity的启动Intent及参数。

4、ActivityStarter.execute
其中ActivityStarter.execute中有如下调用逻辑。


image.png

executeRequest主要做一些初步的启动检查。startActivityUnchecked确保如果启动不成功会删除启动活动。startActivityInner方法决定是否加入到已存在的任务栈顶,计算启动的 Flags,例如是否有 NEW_TASK,并设置给 intent,计算该 Activity 是否要插入到当前现有的任务栈中, 判断栈顶 Activity 是否相同,是否需要复用。
5、ActivityRecord.resumeTopActivityUncheckedLocked
resumeTopActivityUncheckedLocked里面主要调用了Activity的resume,并且调用方法checkReadyForSleep来确保onPause逻辑执行正确。进而走到resumeTopActivityInnerLocked
。该方法中先暂停当前Activity,再启动新的Activity。

@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ...    
    boolean pausing = taskDisplayArea.pauseBackStacks(userLeaving, next);
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
            "resumeTopActivityLocked: Pausing " + mResumedActivity);
         pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);
         ...
mStackSupervisor.startSpecificActivity(next, true, false);
...
   }

6、ActivityStackSupervisor.realStartActivityLocked
其中realStartActivityLocked有如下代码段

// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
        proc.getThread(), r.appToken);

final DisplayContent dc = r.getDisplay().mDisplayContent;
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.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
        r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
        r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));

// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
    lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
    lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);

// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);

其中scheduleTransaction实际是调用IApplicationThread.scheduleTransaction。从IApplicationThread的接口方法可以看出,它其中包含了启动、停止Activity的接口,此外还包含启动、停止Service的接口。

7、ApplicationThread.scheduleTransaction
其实IApplicationThread的实现者就是ApplicationThread。ApplicationThread则是ActivityThread的内部类。来看看scheduleTransaction具体做了些什么,在ApplicationThread中实现如下。

@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    ActivityThread.this.scheduleTransaction(transaction);
}
scheduleTransaction调用了抽象类ClientTransactionHandler的sendMessage方法。而ClientTransactionHandler的实现类其实就是ActivityThread。
public abstract class ClientTransactionHandler {

    // Schedule phase related logic and handlers.

    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
    ...
}

顺着查看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——executeCallbacks——cycleToPath——performLifecycleSequence。

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);
        if (DEBUG_RESOLVER) {
            Slog.d(TAG, tId(transaction) + "Transitioning activity: "
                    + getShortActivityName(r.token, mTransactionHandler)
                    + " to state: " + getStateName(state));
        }
        switch (state) {
            case ON_CREATE:
                mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                        null /* customIntent */);
                break;
            case ON_START:
                mTransactionHandler.handleStartActivity(r.token, mPendingActions);
                break;
            case ON_RESUME:
                mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                        r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                break;
            case ON_PAUSE:
                mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
                        false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                        "LIFECYCLER_PAUSE_ACTIVITY");
                break;
            case ON_STOP:
                mTransactionHandler.handleStopActivity(r.token, 0 /* configChanges */,
                        mPendingActions, false /* finalStateRequest */,
                        "LIFECYCLER_STOP_ACTIVITY");
                break;
            case ON_DESTROY:
                mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                        0 /* configChanges */, false /* getNonConfigInstance */,
                        "performLifecycleSequence. cycling to:" + path.get(size - 1));
                break;
            case ON_RESTART:
                mTransactionHandler.performRestartActivity(r.token, false /* start */);
                break;
            default:
                throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
        }
    }
}

8、ApplicationThread.performLaunchActivity
即scheduleTransaction发送一个启动Activity的消息,交由Handler处理。这个Handler是抽象类ClientTransactionHandler,他的实现是ActivityThread。所以ActivityThread具体的实现了一系列的启动流程。
ON_CREATE则执行handleLaunchActivity,其中performLaunchActivity方法最终完成了Activity对象的创建。并且ActivityThread通过handleResumeActivity方法来调用被启动Activity的onResume这一生命周期方法。
performLaunchActivity主要做了以下几件事:
从ActivityClientRecord中获取待启动的Activity的组件信息;
通过Instrumentation的newActivity方法使用类加载器创建Activity对象;
通过LoadApk的makeAppLication方法来尝试创建Application对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容