Android源碼探究:Activity啟動流程完全解析(下)

概述

本文的內容緊接著上一篇文章Android源碼探究:Activity啟動流程完全解析(上),繼續介紹Activity的啟動流程。

主流程分析

8-1、ActivityManagerService#activityPaused(token)
經過客戶端的跨進程調用,AMS的activityPaused(token)被調用了。

    @Override
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

根據token來獲取Activity所在的ActivityStack,進一步調用activityPausedLocked(params..)

8-2、ActivityStack#activityPausedLocked(params..)

final void activityPausedLocked(IBinder token, boolean timeout) {
    //先從ActivityStack根據token取出對應的ActivityRecord
    final ActivityRecord r = isInStackLocked(token);
    if (r != null) {
        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
        //如果二者相等,表示記錄的需要暫停的Activity已經暫停完畢
        if (mPausingActivity == r) {
            mService.mWindowManager.deferSurfaceLayout();
            try {
                completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
            } finally {
                mService.mWindowManager.continueSurfaceLayout();
            }
            return;
        } else {
            //省略...
        }
    }
    mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}

這里沒什么好說的,我們繼續看completePauseLocked(params..)

8-3、ActivityStack#completePauseLocked(params..)

private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
    ActivityRecord prev = mPausingActivity;

    //省略大部分的代碼...

    if (resumeNext) {
        final ActivityStack topStack = mStackSupervisor.getFocusedStack();
        if (!topStack.shouldSleepOrShutDownActivities()) {
            mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
        } else {
            //...
        }
    }

}

當代碼執行到這里的時候,讀者應該對這個方法resumeFocusedStackTopActivityLocked(params..)有點眼熟吧?上面已經執行過該方法了,接下來的調用鏈都是一樣的了,最終會執行到ActivityStackSupervisor#startSpecificActivityLocked(params..)這個方法,進行Activity的真正啟動過程。

8-4、ActivityStackSupervisor#startSpecificActivityLocked(params..)

void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    //獲取Activity所對應的進程記錄
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    getLaunchTimeTracker().setLaunchTime(r);

    //如果該進程已經啟動了,那么直接開始啟動Activity
    if (app != null && app.thread != null) {
        try {
            //若該Activity的flag不包含多進程標志位 或 不是安卓框架的組件
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                // Don't add this if it is a platform component that is marked
                // to run in multiple processes, because this is actually
                // part of the framework so doesn't make sense to track as a
                // separate apk in the process.
                // 如果它是一個標記為多進程運行的平臺組件,則不要添加該項,
                // 因為這實際上是安卓框架的一部分,因此在進程中作為單獨的apk進行跟蹤是沒有意義的。
                app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                        mService.mProcessStats);
            }
            //真正地啟動一個Activity
            realStartActivityLocked(r, app, andResume, checkConfig);    
            return;
        } catch (RemoteException e) {
            //...
        }

        // If a dead object exception was thrown -- fall through to
        // restart the application.
    }

    //代碼9-1:否則,先啟動一個新的進程,然后再啟動Activity
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

代碼的邏輯很清晰明了,主要是先判斷Activity所對應的進程是否已經存在,如果存在了那就直接去執行真正的啟動Activity過程;如果該進程還不存在,那么就要去啟動一個進程。接下來的分析有兩條路可以走,一是沿著Activity啟動進行分析;二是沿著進程的啟動進行分析。實際上進程的啟動完畢之后也還是要進行Activity的啟動的。也就是說調用了mService.startProcessLocked(params)后,會啟動新的進程,然后ActivityStackSupervisor再次調用realStartActivityLocked(params..)在進程內啟動Activity。
其實,這個調用順序符合這一種情況:在進程A的ActivityA內啟動了進程B的ActivityB,此時先暫停進程A的ActivityA,然后進程B還沒有啟動,那么先啟動進程B,然后再啟動ActivityB。
因此,接下來我們先來看怎樣啟動一個新的進程。


9-1、ActivityManagerService#startProcessLocked(params..)

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

private final boolean startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
        //省略大部分代碼...

        final String entryPoint = "android.app.ActivityThread";
        return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
                runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                startTime);
    } 
}
//一系列startProcessLocked(params..)重載方法的調用
//最終會調用下面的startProcess(params..)方法

private ProcessStartResult startProcess(String hostingType, String entryPoint,
        ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
        String seInfo, String requiredAbi, String instructionSet, String invokeWith,
        long startTime) {
    try {
        final ProcessStartResult startResult;
        if (hostingType.equals("webview_service")) {
            startResult = startWebView(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null,
                    new String[] {PROC_START_SEQ_IDENT + app.startSeq});
        } else {
            startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, invokeWith,
                    new String[] {PROC_START_SEQ_IDENT + app.startSeq});
        }
        return startResult;
    } 
}

中間省略了大部分的重載方法的調用,最后來到了Process.start(params..),把一系列進程有關的信息都傳遞了進去,根據這些信息來創建一個進程。

9-2、Process#start(params..)
這個類的源碼在Android SDK內可以找到,我們直接看它的代碼:

public static final ProcessStartResult start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int runtimeFlags, int mountExternal,
                              int targetSdkVersion,
                              String seInfo,
                              String abi,
                              String instructionSet,
                              String appDataDir,
                              String invokeWith,
                              String[] zygoteArgs) {
    return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}

這里我們需要關注一個參數processClass,當一個進程被啟動后,以processClass為類名的類的main(args)函數會被調用。而這里的processClass是代碼9-1中傳遞進來的“android.app.ActivityThread”。那么也就是說,一個新的進程啟動后,它的ActivityThread的main()函數會最先得到執行。所以,ActivityThread#main()是整個應用程序的入口

9-3、zygoteProcess#start(params..)
代碼執行到了zygoteProcess的start(params..)方法,我們先來看一下代碼的執行:

public final Process.ProcessStartResult start(final String processClass,
        final String niceName,int uid, int gid, int[] gids,
        int runtimeFlags, int mountExternal,int targetSdkVersion,
        String seInfo,String abi,String instructionSet,String appDataDir,
        String invokeWith,String[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
                zygoteArgs);
    } catch{
        //...
    }
}

private Process.ProcessStartResult startViaZygote(params...)throws ZygoteStartFailedEx {
    ArrayList<String> argsForZygote = new ArrayList<String>();

    //為zygote進程添加各種參數...
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    //省略...

    //這里加了鎖,同一時間內只允許一條線程執行創建進程的操作
    synchronized(mLock) {
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

/**
 * 把新進程的參數發給zygote進程,它會創建一個子進程,并返回子進程的pid
 *
 */
@GuardedBy("mLock")
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList<String> args)
        throws ZygoteStartFailedEx {
    try {
        //這里的跨進程通信,使用的是socket通信機制
        //由于這里都是在鎖的機制下執行,所以不會出現并發錯誤  
        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;

        //把所有新進程的參數都寫入緩沖區
        writer.write(Integer.toString(args.size()));
        writer.newLine();

        for (int i = 0; i < sz; i++) {
            String arg = args.get(i);
            writer.write(arg);
            writer.newLine();
        }

        writer.flush();

        // Should there be a timeout on this?
        Process.ProcessStartResult result = new Process.ProcessStartResult();

        //讀取zygote進程返回的值,這就是新進程的pid
        result.pid = inputStream.readInt();
        result.usingWrapper = inputStream.readBoolean();

        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }
        return result;
    } 
}

zygote到底是何方神圣呢?其實在安卓系統啟動的過程中,zygote進程就會被啟動,它負責了整個frameworks層和application層的所有進程的創建和啟動工作。也就是說,所有的進程都是它孕育出來的,都是它的子進程。同時,zygote的中文意思受精卵剛好與它的行為相符合。
需要注意的是,上面的代碼都是運行在AMS內,只不過最后通過socket跨進程通信的方式通知了zygote進程來fork一個子進程,并且獲取到了子進程的pid。該子進程創建、啟動完畢之后,ActivityThread#main()方法就得到了調用。


10-1、ActivityThread#main()
ActivityThread的main()方法可以說是我們應用程序的開端,它運行在一個新的進程空間內。當一個新的進程啟動完畢開始運行后,它首先要做的是通知AMS它被啟動了,因為此時AMS還等著它去執行啟動Activity的后續流程呢。我們來看看main()方法做了什么工作:

public static void main(String[] args) {
    //初始化環境
    Environment.initForCurrentUser();

    // Set the reporter for event logging in libcore
    EventLogger.setReporter(new EventLoggingReporter());

    // Make sure TrustedCertificateStore looks in the right place for CA certificates
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);

    Process.setArgV0("<pre-initialized>");

    //為主線程準備Looper
    Looper.prepareMainLooper();

    //從命令行參數中獲取序列號
    long startSeq = 0;
    if (args != null) {
        for (int i = args.length - 1; i >= 0; --i) {
            if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                startSeq = Long.parseLong(
                        args[i].substring(PROC_START_SEQ_IDENT.length()));
            }
        }
    }
    //創建ActivityThread的實例
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);    //通知AMS進行綁定操作

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    Looper.loop();      //開啟主線程的消息循環

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

代碼的邏輯很清晰,關鍵的地方上面也有注釋。可以看出,在main()函數的最后,開啟了主線程的消息循環,通過Handler和Looper的組合,可以不斷地處理AMS、WMS發過來的消息請求等,有關主線程消息循環的內容,有興趣的可以自行查閱相關的信息,這里不做展開講述。我們的關注點放在thread.attach(false,startSeq)這行代碼內,我們看看它做了什么工作吧。

10-2、ActivityThread#attach(params..)

private void attach(boolean system, long startSeq) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        //獲取AMS在客戶端的代理對象
        final IActivityManager mgr = ActivityManager.getService();
        try {
            //進行跨進程通信,通知AMS進行綁定操作
            //這里的mAppThread就是ApplicationThread,在ActivityThread
            //被實例化的時候,它也被實例化了。
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        
    } else {
        //...
    }
    //...
}

上面的代碼出現了ApplicationThread對象,它在前面已經出現過很多次了,它是一個Binder對象,用于AMS來跨進程與APP進行消息通信。這里通過Binder跨進程通信,調用了AMS的attachApplication(params..)方法。我們再次打開AMS的代碼,找到該方法。(需要注意的是:應用程序的主線程執行完該方法之后,繼續進行消息循環,以等待下一次AMS的消息。)

10-3、ActivityManagerService#attachApplication(params..)

@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        //..
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
    }
}

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
    ProcessRecord app;
    long startTime = SystemClock.uptimeMillis();
    //根據pid來獲取進程記錄
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid);
        }
    } else {
        app = null;
    }

    //ProcessRecord保存了當前的IApplicationThread,即保存了客戶端的一個代理對象
    //AMS能根據該Binder對象快速找到所指的應用
    app.makeActive(thread, mProcessStats);  
    
    //省略大部分代碼...

        if (app.isolatedEntryPoint != null) {
            //...
        } else if (app.instr != null) {
            //代碼11-1、跨進程調用ApplicationThread的方法,告訴APP端有關該進程的信息
            thread.bindApplication(processName, appInfo, providers,
                    app.instr.mClass,
                    profilerInfo, app.instr.mArguments,
                    app.instr.mWatcher,
                    app.instr.mUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, isAutofillCompatEnabled);
            } else {
                //...
            }
            
        } 

    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
            //代碼12-1、告訴ActivityStackSupervisor,該app已經完成了綁定操作,可以啟動一個Activity了
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } 
    }
    return true;
}

上面已經省略了大部分的代碼,很多都是異常狀態的處理以及初始化等邏輯,核心在于thread.bindApplication(params..)mStackSupervisor.attachApplicationLocked(app)這兩個方法的調用上。前一行代碼通過IApplicationThread跨進程通信,調用了APP端的相應方法,把有關進程的重要信息傳遞了過去。這樣便完成從客戶端到服務端的綁定操作。后一行代碼,通過ActivityStackSupervisor來找到對應的ActivityStack,然后進行綁定,這樣便完成了從服務端到客戶端的綁定操作。通過這兩個操作,客戶端的應用程序知道了自己的應用信息、進程信息等;而服務端則知道了客戶端的Binder代理對象,方便之后的跨進程操作。


11-1、ApplicationThread#bindApplication(params..)
我們先來看該方法的調用,我們又從AMS進程回到了應用進程:

public final void bindApplication(params..) {

    if (services != null) {

        // Setup the service cache in the ServiceManager
        ServiceManager.initServiceCache(services);
    }

    setCoreSettings(coreSettings);

    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    //省略賦值代碼..
        
    //通過Handler發送消息
    sendMessage(H.BIND_APPLICATION, data);
}

由此可見,App的有關信息從AMS傳遞了過來,并保存在了AppBindData這個對象內。接著,就是我們熟悉的發送消息過程,通過Handler切換到主線程,在主線程內處理這個消息。代碼如下:

public void handleMessage(Message msg) {
    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;        
    }
    Object obj = msg.obj;
    if (obj instanceof SomeArgs) {
        ((SomeArgs) obj).recycle();
    }
}

得益于主線程的消息循環,當H接受到BIND_APPLICATION的消息時,就能馬上開始處理這個消息,處理完畢后繼續消息循環。

11-2、ActivityThread#handleBindApplication(data)

private void handleBindApplication(AppBindData data) {
    //省略大部分代碼...

    //創建上下文環境context
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
        
    Application app;
    try {
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        
        //....
        try {
            mInstrumentation.callApplicationOnCreate(app);
        }
    }
}

以上省略了絕大部分的代碼,很多都是初始化代碼,比如加載各種庫等。當Application初始化完畢之后,調用了mInstrumentation.callApplicationOnCreate(app)

11-3、Instrumentation#callApplicationOnCreate(app)

public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }

很簡單,調用了Application#onCreate()方法,也就是我們業務層常重寫的方法之一,代碼執行到這里,應用程序的初始化已經完成了。下面就是在應用程序的基礎上啟動一個Activity了。


12-1、ActivityStackSupervisor#attachApplicationLocked(app)
回到10-3的代碼,繼續往下執行,接著AMS就會調用mStackSupervisor.attachApplicationLocked(app)方法,可想而知,在方法的內部,應該是要啟動一個Activity了。因為一切的準備工作都已經完成了。

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    final String processName = app.processName;
    boolean didSomething = false;
    for (...) {
        for (...) {
            for (int i = 0; i < size; i++) {
                final ActivityRecord activity = mTmpActivityList.get(i);

                //如果該ActivityRecord的進程字段為空 并且進程uid與Activity的進程id相同
                //并且 進程名字與Activity的進程名字相同
                if (activity.app == null && app.uid == activity.info.applicationInfo.uid
                        && processName.equals(activity.processName)) {
                    try {
                        //啟動該Activity
                        if (realStartActivityLocked(activity, app,
                                top == activity /* andResume */, true /* checkConfig */)) {
                            didSomething = true;
                        }
                    } 
                }
            }
        }
    }
    return didSomething;
}

上面代碼的邏輯主要是遍歷所有的任務棧,找到活躍的任務棧后,再在其中找到需要啟動的Activity,將它啟動。啟動的邏輯放在了realStartActivityLocked(params..),終于,我們又看到了這個方法,殊途同歸。

12-2、ActivityStackSupervisor#realStartActivityLocked(params..)

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {

    //這里進行了判斷,如果有Activity處于未暫停的狀態,則不能啟動一個新的Activity
    //由于我們是從客戶端通知server來啟動一個Activity的,因此已經不存在未暫停的Activity了
    if (!allPausedActivitiesComplete()) {   
        return false;
    }

    final TaskRecord task = r.getTask();
    final ActivityStack stack = task.getStack();

    try {
            //創建一個客戶端的事務
            final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                    r.appToken);
            //添加callback,留意這里的添加了LaunchActivityItem
            clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                    System.identityHashCode(r), r.info,
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                    profilerInfo));

            //為該事務的目標設置為ResumeActivityItem,即啟動一個Activity,并改變它
            //的生命周期到Resumed狀態
            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
                lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
            } 
            clientTransaction.setLifecycleStateRequest(lifecycleItem);

            //通過事務管理器執行一個事務
            mService.getLifecycleManager().scheduleTransaction(clientTransaction);
        } 
    return true;
}

可以看到,我們再次遇到了熟悉的ClientTransaction,前面解析暫停Activity時也遇到它,那么接下來的邏輯應該就是與暫停的邏輯差不多了,只不過現在的ActivityLifecycleItem變成了ResumeActivityItem,即Activity的目標狀態是resumed。接下來的調用鏈與前面見過的是一致的,即:ClientLifecycleManager#scheduleTransaction(clientTransaction)
——>ClientTransaction.schedule()
——>IApplicationThread.scheduleTransaction(this)
——>ActivityThread#scheduleTransaction(transaction)
——>H#handleMessage(msg)
——>TransactionExecutor#execute(transaction)
其中,通過IApplicationThread這個Binder對象進行了跨進程調用,調用了APP端的方法,此時從AMS進程切換到了我們的應用進程。緊接著,通過Handler機制切換到了主線程,并在主線程處理EXECUTE_TRANSACTION這個消息,接著進一步交給TransactionExecutor來處理這個事務。


13-1、TransactionExecutor#execute(transaction)
在代碼7-1已經介紹過這個方法了,我們再來簡單看一下就行:

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

在代碼12-2中,我們有留意到初始化clientTransaction時,為它添加了一個callback,即LaunchActivityItem,那么這里首先會執行executeCallbacks(transaction)方法。

13-2、TransactionExecutor#executeCallbacks(transaction)

public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    if (callbacks == null) {
        // No callbacks to execute, return early.
        return;
    }
    log("Resolving callbacks");

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

    //根據前面的代碼,這里的size為1
    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        log("Resolving callback: " + item);

        //這里的Item實際上就是LaunchActivityItem.
        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);

        //...
    }
}

在方法內部調用了LaunchActivityItem的相關方法,其中關鍵是LaunchActivityItem#execute(params..)

13-3、LaunchActivityItem#execute(params..)

public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    //實例化一個ActivityClientRecord
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mIsForward,
            mProfilerInfo, client);
    //實際上調用的是ActivityThread的handleLaunchActivity方法
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

這里的ClientTransactionHandlerActivityThread的父類,而ActivityThread重寫了該方法,因此我們到ActivityThread尋找該方法。

13-4、ActivityThread#handleLaunchActivity(params..)

public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    //....

    final Activity a = performLaunchActivity(r, customIntent);

    //...

    return a;
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    
    //省略部分代碼..

    ActivityInfo aInfo = r.activityInfo;
    ContextImpl appContext = createBaseContextForActivity(r);   //創建Context
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);    //創建一個新的Activity
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } 

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (activity != null) {
            appContext.setOuterContext(activity);
            //activity綁定application
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);

            
            if (r.isPersistable()) {
                //前面創建了Activity,接下來觸發它的生命周期方法
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }

            r.activity = activity;
        }
        r.setState(ON_CREATE);  //設置Activity此時的狀態為onCreate

        mActivities.put(r.token, r);

    return activity;
}

經過一系列的創建、初始化過程,終于到了Instrumentation#callActivityOnCreate(params..),顯然,這里就是觸發Activity生命周期方法的地方了。

13-5、Instrumentation#callActivityOnCreate(params..)

public void callActivityOnCreate(Activity activity, Bundle icicle) {
     prePerformCreate(activity);
     activity.performCreate(icicle);
     postPerformCreate(activity);
}

沒什么好說的,下一步就是Activity#performCreate(bundle)

final void performCreate(Bundle icicle) {
    performCreate(icicle, null);
}

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    if (persistentState != null) {
        onCreate(icicle, persistentState);  
    } else {
        onCreate(icicle);   //onCreate()生命周期方法調用
    }
    writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate");
    mActivityTransitionState.readState(icicle);

    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
            com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mFragments.dispatchActivityCreated();   //告訴Fragment分發create事件
    mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
}

最后,終于來到了Activity#onCreate()方法,也這就是我們應用Activity默認重寫的一個方法。到了這一步,一個Activity終于真正地創建、啟動成功了。但還沒有完成,因為我們的目標狀態是resumed,所以我們還要把Activity的狀態逐步切換到onResume狀態。
讓我們回到代碼13-1的executeLifecycleState(transaction),這個方法讀者應該也是熟悉的了,因為在處理pause狀態時也曾經遇到過了。那么接下來的邏輯就顯而易見了,具體的邏輯就在代碼7-2處,只不過現在的狀態路徑變成了:onStart和onResume,也就是會分別調用ActivityThread#handleStartActivityActivityThread#handleResumeActivity;接著進一步調用到Activity#performStart()Activity#performResume()。最后,我們熟悉的生命周期方法onStart()onResume()都會得到調用。

本文到這里就告一段落了,整篇文章很長,為耐心看到這里的你點贊~希望這篇文章能對您有所裨益,謝謝閱讀!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容