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阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容