高级UI<第六篇>:从源码分析Activity启动流程(Android 9.0)

熟悉Activity的启动流程是学习高级UI系列的基础,随着Android SDK版本的不断变化,Activity的启动流程也在变化,本文就以Android 9.0为例,分析Activity的启动流程。

    Intent intent = new Intent(MainActivity.this, SceneTransitionActivity.class);
    startActivity(intent);

以上两句代码相信大家已经很熟悉了,它的作用就是启动一个Activity,本文就以这个为起点开始跟踪源码。

在源码的Activity.java 有这样一个方法,实现Activity的启动

/**
 * Same as {@link #startActivity(Intent, Bundle)} with no options
 * specified.
 *
 * @param intent The intent to start.
 *
 * @throws android.content.ActivityNotFoundException
 *
 * @see #startActivity(Intent, Bundle)
 * @see #startActivityForResult
 */
@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

继续往下跟踪:

/**
 * Launch a new activity.  You will not receive any information about when
 * the activity exits.  This implementation overrides the base version,
 * providing information about
 * the activity performing the launch.  Because of this additional
 * information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not
 * required; if not specified, the new activity will be added to the
 * task of the caller.
 *
 * <p>This method throws {@link android.content.ActivityNotFoundException}
 * if there was no Activity found to run the given Intent.
 *
 * @param intent The intent to start.
 * @param options Additional options for how the Activity should be started.
 * See {@link android.content.Context#startActivity(Intent, Bundle)}
 * Context.startActivity(Intent, Bundle)} for more details.
 *
 * @throws android.content.ActivityNotFoundException
 *
 * @see #startActivity(Intent)
 * @see #startActivityForResult
 */
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

继续跟踪:

/**
 * Launch an activity for which you would like a result when it finished.
 * When this activity exits, your
 * onActivityResult() method will be called with the given requestCode.
 * Using a negative requestCode is the same as calling
 * {@link #startActivity} (the activity is not launched as a sub-activity).
 *
 * <p>Note that this method should only be used with Intent protocols
 * that are defined to return a result.  In other protocols (such as
 * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
 * not get the result when you expect.  For example, if the activity you
 * are launching uses {@link Intent#FLAG_ACTIVITY_NEW_TASK}, it will not
 * run in your task and thus you will immediately receive a cancel result.
 *
 * <p>As a special case, if you call startActivityForResult() with a requestCode
 * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
 * activity, then your window will not be displayed until a result is
 * returned back from the started activity.  This is to avoid visible
 * flickering when redirecting to another activity.
 *
 * <p>This method throws {@link android.content.ActivityNotFoundException}
 * if there was no Activity found to run the given Intent.
 *
 * @param intent The intent to start.
 * @param requestCode If >= 0, this code will be returned in
 *                    onActivityResult() when the activity exits.
 * @param options Additional options for how the Activity should be started.
 * See {@link android.content.Context#startActivity(Intent, Bundle)}
 * Context.startActivity(Intent, Bundle)} for more details.
 *
 * @throws android.content.ActivityNotFoundException
 *
 * @see #startActivity
 */
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // If this start is requesting a result, we can avoid making
            // the activity visible until the result is received.  Setting
            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
            // activity hidden during this time, to avoid flickering.
            // This can only be done when a result is requested because
            // that guarantees we will get information back when the
            // activity is finished, no matter what happens to it.
            mStartedActivity = true;
        }

        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // Note we want to go through this method for compatibility with
            // existing applications that may have overridden it.
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

源码中的mParent为Activity对象,当第一次启动时,mParent才会为空。

当第一次启动时,执行

mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);

当非第一次启动时,执行

mParent.startActivityFromChild(this, intent, requestCode, options)

当非第一次启动时,还是会执行mInstrumentation.execStartActivity方法,所以接下来开始研究mInstrumentation.execStartActivity方法。

mInstrumentation是Instrumentation类的变量,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作

看一下源码:

/**
 * Execute a startActivity call made by the application.  The default 
 * implementation takes care of updating any active {@link ActivityMonitor}
 * objects and dispatches this call to the system activity manager; you can
 * override this to watch for the application to start an activity, and 
 * modify what happens when it does. 
 *
 * <p>This method returns an {@link ActivityResult} object, which you can 
 * use when intercepting application calls to avoid performing the start 
 * activity action but still return the result the application is 
 * expecting.  To do this, override this method to catch the call to start 
 * activity so that it returns a new ActivityResult containing the results 
 * you would like the application to see, and don't call up to the super 
 * class.  Note that an application is only expecting a result if 
 * <var>requestCode</var> is &gt;= 0.
 *
 * <p>This method throws {@link android.content.ActivityNotFoundException}
 * if there was no Activity found to run the given Intent.
 *
 * @param who The Context from which the activity is being started.
 * @param contextThread The main thread of the Context from which the activity
 *                      is being started.
 * @param token Internal token identifying to the system who is starting 
 *              the activity; may be null.
 * @param target Which activity is performing the start (and thus receiving 
 *               any result); may be null if this call is not being made
 *               from an activity.
 * @param intent The actual Intent to start.
 * @param requestCode Identifier for this request's result; less than zero 
 *                    if the caller is not expecting a result.
 * @param options Addition options.
 *
 * @return To force the return of a particular result, return an 
 *         ActivityResult object containing the desired data; otherwise
 *         return null.  The default implementation always returns null.
 *
 * @throws android.content.ActivityNotFoundException
 *
 * @see Activity#startActivity(Intent)
 * @see Activity#startActivityForResult(Intent, int)
 * @see Activity#startActivityFromChild
 *
 * {@hide}
 */
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                ActivityResult result = null;
                if (am.ignoreMatchingSpecificIntents()) {
                    result = am.onStartActivity(intent);
                }
                if (result != null) {
                    am.mHits++;
                    return result;
                } else if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

execStartActivity方法是Instrumentation中的一个方法,其中启动Activity的代码如下:

        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);

熟悉Binder机制的都可以很容易找到ActivityManager.getService()对应的其实就是ActivityManagerService类,ActivityManagerService类中的startActivity方法源码如下:

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

继续跟踪:

@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
            true /*validateIncomingUser*/);
}

继续跟踪:

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
        boolean validateIncomingUser) {
    enforceNotIsolatedCaller("startActivity");

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

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

}

最终执行了execute方法

/**
 * Starts an activity based on the request parameters provided earlier.
 * @return The starter result.
 */
int execute() {
    try {
        // TODO(b/64750076): Look into passing request directly to these methods to allow
        // for transactional diffs and preprocessing.
        if (mRequest.mayWait) {
            return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                    mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                    mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                    mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                    mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                    mRequest.inTask, mRequest.reason,
                    mRequest.allowPendingRemoteAnimationRegistryLookup);
        } else {
            return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                    mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                    mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                    mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                    mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                    mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                    mRequest.outActivity, mRequest.inTask, mRequest.reason,
                    mRequest.allowPendingRemoteAnimationRegistryLookup);
        }
    } finally {
        onExecutionComplete();
    }
}

从源码分析,mRequest.mayWait = true,所以接下来会执行到startActivityMayWait方法。

private int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, Intent intent, String resolvedType,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, WaitResult outResult,
        Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
        int userId, TaskRecord inTask, String reason,
        boolean allowPendingRemoteAnimationRegistryLookup) {
    // Refuse possible leaked file descriptors
    if (intent != null && intent.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
 ..............................(省略部分代码)
        final ActivityRecord[] outRecord = new ActivityRecord[1];
        int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                allowPendingRemoteAnimationRegistryLookup);

 ..............................(省略部分代码)
}

继续往下走:

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
        ActivityRecord[] outActivity, TaskRecord inTask, String reason,
        boolean allowPendingRemoteAnimationRegistryLookup) {

    if (TextUtils.isEmpty(reason)) {
        throw new IllegalArgumentException("Need to specify a reason.");
    }
    mLastStartReason = reason;
    mLastStartActivityTimeMs = System.currentTimeMillis();
    mLastStartActivityRecord[0] = null;

    mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
            callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
            inTask, allowPendingRemoteAnimationRegistryLookup);

    if (outActivity != null) {
        // mLastStartActivityRecord[0] is set in the call to startActivity above.
        outActivity[0] = mLastStartActivityRecord[0];
    }

    return getExternalResult(mLastStartActivityResult);
}

继续往下走:

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        SafeActivityOptions options,
        boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
        TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {

 ...............(省略部分代码)

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
            resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
            mSupervisor, checkedOptions, sourceRecord);
    if (outActivity != null) {
        outActivity[0] = r;
    }

 ...............(省略部分代码)

    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
            true /* doResume */, checkedOptions, inTask, outActivity);
}

继续往下走:

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
    int result = START_CANCELED;
    try {
        mService.mWindowManager.deferSurfaceLayout();
        result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, doResume, options, inTask, outActivity);
    } finally {
        // If we are not able to proceed, disassociate the activity from the task. Leaving an
        // activity in an incomplete state can lead to issues, such as performing operations
        // without a window container.
        final ActivityStack stack = mStartActivity.getStack();
        if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
            stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
                    null /* intentResultData */, "startActivity", true /* oomAdj */);
        }
        mService.mWindowManager.continueSurfaceLayout();
    }

    postStartActivityProcessing(r, result, mTargetStack);

    return result;
}

继续往下走:

// Note: This method should only be called from {@link startActivity}.
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {

    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor);

    computeLaunchingTaskFlags();

    computeSourceStack();

    mIntent.setFlags(mLaunchFlags);

    ActivityRecord reusedActivity = getReusableIntentActivity();

 ...............(省略部分代码)

    if (mStartActivity.packageName == null) {
        final ActivityStack sourceStack = mStartActivity.resultTo != null
                ? mStartActivity.resultTo.getStack() : null;
        if (sourceStack != null) {
            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                    null /* data */);
        }
        ActivityOptions.abort(mOptions);
        return START_CLASS_NOT_FOUND;
    }

 ...............(省略部分代码)

    return START_SUCCESS;
}

我来分析一下以上源码:

【重置启动参数】

    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor);

【赋值启动标志】 将mLaunchFlags赋值

    computeLaunchingTaskFlags();

【将mLaunchFlags赋值到Intent中】

    mIntent.setFlags(mLaunchFlags);

【获取ActivityRecord对象】

代码如下:

   ActivityRecord reusedActivity = getReusableIntentActivity();

解析getReusableIntentActivity()方法之前需要先了解几个概念:

ActivityRecord:ActivityStack的管理对象,每个Activity在AMS(ActivityManagerService)对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像

ActivityStack:Activity在AMS(ActivityManagerService)的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程

TaskRecord:AMS(ActivityManagerService)抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS(ActivityManagerService)用TaskRecord确保Activity启动和退出的顺序。

ActivityStackSupervisor:负责所有Activity栈的管理。内部管理了mHomeStack、mFocusedStack和mLastFocusedStack三个Activity栈。其中,mHomeStack管理的是Launcher相关的Activity栈;mFocusedStack管理的是当前显示在前台Activity的Activity栈;mLastFocusedStack管理的是上一次显示在前台Activity的Activity栈

getReusableIntentActivity()的源码就不贴出来了,大致的意思是根据启动模式和启动标志拿到ActivityRecord对象,ActivityRecord对象可以理解为Activity。

该方法注释的意思是:决定新的Activity是否应该插入到现有的Task中。如果不是,则返回空值,或者返回包含应向其中添加新Activity的Task的ActivityRecord

reusedActivity变量就相当于是一个Activity了,所以程序走到这里,就等于一个Activity创建完成了,那么又在哪里启动这个Activity呢?

这段源码还有一个核心代码,如下:

        Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
        sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                null /* data */);

查看下源码:

void sendActivityResultLocked(int callingUid, ActivityRecord r,
        String resultWho, int requestCode, int resultCode, Intent data) {

    if (callingUid > 0) {
        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                data, r.getUriPermissionsLocked(), r.userId);
    }

    if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
            + " : who=" + resultWho + " req=" + requestCode
            + " res=" + resultCode + " data=" + data);
    if (mResumedActivity == r && r.app != null && r.app.thread != null) {
        try {
            ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
            list.add(new ResultInfo(resultWho, requestCode,
                    resultCode, data));
            mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                    ActivityResultItem.obtain(list));
            return;
        } catch (Exception e) {
            Slog.w(TAG, "Exception thrown sending result to " + r, e);
        }
    }

    r.addResultLocked(null, resultWho, requestCode, resultCode, data);
}

它的核心代码是:

        mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                ActivityResultItem.obtain(list));

以上代码就是Activity启动流程中最为重要的代码了,

mService就是ActivityManagerService变量,从系统Activity管理服务对象中获取Activity生命周期管理实例(ClientLifecycleManager实例)。

ClientLifecycleManager:用于管理Activity生命周期的管理类

启动Activity最终调用了ClientLifecycleManager类的scheduleTransaction方法。

继续跟踪源码:

void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
        @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
    final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
            stateRequest);
    scheduleTransaction(clientTransaction);
}

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

其核心代码是:

transaction.schedule();

继续跟踪ClientTransaction类中的schedule方法:

/**
 * Schedule the transaction after it was initialized. It will be send to client and all its
 * individual parts will be applied in the following sequence:
 * 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
 *    that needs to be done before actually scheduling the transaction for callbacks and
 *    lifecycle state request.
 * 2. The transaction message is scheduled.
 * 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
 *    all callbacks and necessary lifecycle transitions.
 */
public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

mClient是指IApplicationThread接口,也就是说执行IApplicationThread接口的scheduleTransaction方法,从上一篇文章就讲到,IApplicationThread其实就是ActivityThread的内部类ApplicationThread(Binder通信),下面贴出ApplicationThread类的scheduleTransaction方法,如下:

    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        ActivityThread.this.scheduleTransaction(transaction);
    }

也就是说,假如Android SDK版本是28(Android 9.0),那么Activity的启动入口是:ActivityThread.ApplicationThread.scheduleTransaction(ClientTransaction transaction),点击桌面图标(Launcher)启动App,第一次启动的Activity入口也是这个方法。

接下来继续往下走:

ActivityThread.this.scheduleTransaction(transaction);

这句代码其实执行的是ActivityThread的scheduleTransaction方法,ActivityThread继承了一个抽象类ClientTransactionHandler,在这个抽象类中找到了scheduleTransaction方法,如下:

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

继续往下走:

执行到ActivityThread类中sendMessage方法

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    if (DEBUG_MESSAGES) Slog.v(
        TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
        + ": " + arg1 + " / " + obj);
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;
    if (async) {
        msg.setAsynchronous(true);
    }
    mH.sendMessage(msg);
}

所以,得出一个结论,启动Activity,其实就是利用Handler机制,发送一个Message,Message的what值为:H.EXECUTE_TRANSACTION,H是ActivityThread的内部类,实际上是一个Handler,那么这个Message在哪里接收呢?这个比较好找,接收的方法必然是H的handleMessage方法,如下:

    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case BIND_APPLICATION:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case EXIT_APPLICATION:
                if (mInitialApplication != null) {
                    mInitialApplication.onTerminate();
                }
                Looper.myLooper().quit();
                break;
            case RECEIVER:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
                handleReceiver((ReceiverData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case CREATE_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                handleCreateService((CreateServiceData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case BIND_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                handleBindService((BindServiceData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case UNBIND_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
                handleUnbindService((BindServiceData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case SERVICE_ARGS:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
                handleServiceArgs((ServiceArgsData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case STOP_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
                handleStopService((IBinder)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case CONFIGURATION_CHANGED:
                handleConfigurationChanged((Configuration) msg.obj);
                break;
            case CLEAN_UP_CONTEXT:
                ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
                cci.context.performFinalCleanup(cci.who, cci.what);
                break;
            case GC_WHEN_IDLE:
                scheduleGcIdler();
                break;
            case DUMP_SERVICE:
                handleDumpService((DumpComponentInfo)msg.obj);
                break;
            case LOW_MEMORY:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
                handleLowMemory();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case PROFILER_CONTROL:
                handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2);
                break;
            case CREATE_BACKUP_AGENT:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
                handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case DESTROY_BACKUP_AGENT:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
                handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case SUICIDE:
                Process.killProcess(Process.myPid());
                break;
            case REMOVE_PROVIDER:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
                completeRemoveProvider((ProviderRefCount)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case ENABLE_JIT:
                ensureJitEnabled();
                break;
            case DISPATCH_PACKAGE_BROADCAST:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
                handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case SCHEDULE_CRASH:
                throw new RemoteServiceException((String)msg.obj);
            case DUMP_HEAP:
                handleDumpHeap((DumpHeapData) msg.obj);
                break;
            case DUMP_ACTIVITY:
                handleDumpActivity((DumpComponentInfo)msg.obj);
                break;
            case DUMP_PROVIDER:
                handleDumpProvider((DumpComponentInfo)msg.obj);
                break;
            case SLEEPING:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
                handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case SET_CORE_SETTINGS:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
                handleSetCoreSettings((Bundle) msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case UPDATE_PACKAGE_COMPATIBILITY_INFO:
                handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
                break;
            case UNSTABLE_PROVIDER_DIED:
                handleUnstableProviderDied((IBinder)msg.obj, false);
                break;
            case REQUEST_ASSIST_CONTEXT_EXTRAS:
                handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
                break;
            case TRANSLUCENT_CONVERSION_COMPLETE:
                handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
                break;
            case INSTALL_PROVIDER:
                handleInstallProvider((ProviderInfo) msg.obj);
                break;
            case ON_NEW_ACTIVITY_OPTIONS:
                Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
                onNewActivityOptions(pair.first, pair.second);
                break;
            case ENTER_ANIMATION_COMPLETE:
                handleEnterAnimationComplete((IBinder) msg.obj);
                break;
            case START_BINDER_TRACKING:
                handleStartBinderTracking();
                break;
            case STOP_BINDER_TRACKING_AND_DUMP:
                handleStopBinderTrackingAndDump((ParcelFileDescriptor) msg.obj);
                break;
            case LOCAL_VOICE_INTERACTION_STARTED:
                handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
                        (IVoiceInteractor) ((SomeArgs) msg.obj).arg2);
                break;
            case ATTACH_AGENT: {
                Application app = getApplication();
                handleAttachAgent((String) msg.obj, app != null ? app.mLoadedApk : null);
                break;
            }
            case APPLICATION_INFO_CHANGED:
                mUpdatingSystemConfig = true;
                try {
                    handleApplicationInfoChanged((ApplicationInfo) msg.obj);
                } finally {
                    mUpdatingSystemConfig = false;
                }
                break;
            case RUN_ISOLATED_ENTRY_POINT:
                handleRunIsolatedEntryPoint((String) ((SomeArgs) msg.obj).arg1,
                        (String[]) ((SomeArgs) msg.obj).arg2);
                break;
            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;
            case RELAUNCH_ACTIVITY:
                handleRelaunchActivityLocally((IBinder) msg.obj);
                break;
        }
        Object obj = msg.obj;
        if (obj instanceof SomeArgs) {
            ((SomeArgs) obj).recycle();
        }
        if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
    }

找到启动Activity传递的what: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方法:

/**
 * Resolve transaction.
 * First all callbacks will be executed in the order they appear in the list. If a callback
 * requires a certain pre- or post-execution state, the client will be transitioned accordingly.
 * Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
 * either remain in the initial state, or last state needed by a callback.
 */
public void execute(ClientTransaction transaction) {
    final IBinder token = transaction.getActivityToken();
    log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

    executeCallbacks(transaction);

    executeLifecycleState(transaction);
    mPendingActions.clear();
    log("End resolving transaction");
}

executeLifecycleState方法:

/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
    final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
    if (lifecycleItem == null) {
        // No lifecycle request, return early.
        return;
    }
    log("Resolving lifecycle state: " + lifecycleItem);

    final IBinder token = transaction.getActivityToken();
    final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

    if (r == null) {
        // Ignore requests for non-existent client records for now.
        return;
    }

    // Cycle to the state right before the final requested state.
    cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

    // Execute the final transition with proper parameters.
    lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
    lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

cycleToPath方法

/**
 * Transition the client between states with an option not to perform the last hop in the
 * sequence. This is used when resolving lifecycle state request, when the last transition must
 * be performed with some specific parameters.
 */
private void cycleToPath(ActivityClientRecord r, int finish,
        boolean excludeLastState) {
    final int start = r.getLifecycleState();
    log("Cycle from: " + start + " to: " + finish + " excludeLastState:" + excludeLastState);
    final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
    performLifecycleSequence(r, path);
}

path为生命周期的路径,将生命周期的路径传递到performLifecycleSequence方法。

/** Transition the client through previously initialized state sequence. */
private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
    final int size = path.size();
    for (int i = 0, state; i < size; i++) {
        state = path.get(i);
        log("Transitioning to state: " + state);
        switch (state) {
            case ON_CREATE:
                mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                        null /* customIntent */);
                break;
            case ON_START:
                mTransactionHandler.handleStartActivity(r, 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, false /* show */,
                        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);
        }
    }
}

以上代码中通过for循环,获取path中Activity生命周期的状态依次执行,启动Activity的状态顺序是:ON_CREATEON_STARTON_RESUMEperformLifecycleSequence方法的代码就是Activity生命周期的体现。

启动Activity的本质其实就是通过Handler机制发送消息,当接收到这个消息的时候,根据what值判断怎么走Activity的生命周期。

当Activity从后台切换到前台、从前台切换到后台、或者销毁Activity,它们的本质也是发送一个消息,这里就不贴出来了。

总结:

Activity的启动其实就是:ActivityThread和ActivityManagerService之间通过Binder机制跨进程通信,从ActivityThread调用ActivityManagerService的startActivity方法,紧接着调用Activity生命周期管理类执行scheduleTransaction方法,最后再次利用Binder机制使ActivityManagerService和ActivityThread的内部类ApplicationThread通信,将程序切换到应用,由应用本身发送Message(handler机制),并处理Activity的生命周期。

[本章完...]

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

推荐阅读更多精彩内容