Android 10 App启动分析之Activity启动篇

Posted 小陈乱敲代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 10 App启动分析之Activity启动篇相关的知识,希望对你有一定的参考价值。

上一篇:

android 10 App启动分析之进程创建篇(一)

上一篇文章,我们探讨了App启动过程中进程创建及初始化的流程,这篇文章我们接着上篇的内容,继续探讨App的Application和Activity的创建及启动流程。


让我们把目光聚焦到ActivityThread的main方法上。

ActivityThread的源码路径为 /frameworks/base/core/java/android/app/ActivityThread

public static void main(String[] args) 
      ...
       
       //请注意这句话,主线程Looper在此处做了prepare的操作
       Looper.prepareMainLooper();

       // Find the value for @link #PROC_START_SEQ_IDENT if provided on the command line.
       // It will be in the format "seq=114"
       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 thread = new ActivityThread();
       thread.attach(false, startSeq);

       if (sMainThreadHandler == null) 
           //获取主线程的handler,其实就是ActivityThread里的mH变量
           sMainThreadHandler = thread.getHandler();
       

       //开始循环获取主线程Message消息
       Looper.loop();

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

继续从ActivityThread的attach方法往下追踪。

private void attach(boolean system, long startSeq) 
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) 
            //执行此分支
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try 
                mgr.attachApplication(mAppThread, startSeq);
             catch (RemoteException ex) 
                throw ex.rethrowFromSystemServer();
            
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() 
                @Override public void run() 
                    if (!mSomeActivitiesChanged) 
                        return;
                    
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) 
                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;
                        try 
                            ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
                         catch (RemoteException e) 
                            throw e.rethrowFromSystemServer();
                        
                    
                
            );
         else 
            ... 
        

        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> 
            synchronized (mResourcesManager) 
                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) 
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());

                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) 
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    
                
            
        ;
        ViewRootImpl.addConfigCallback(configChangedCallback);
     

上述代码调用了IActivityManagerattachApplication方法,并传入了当前的ActivityThread对象以及启动序列号。我们将目光转向ActivityManagerService

 @Override
   public final void attachApplication(IApplicationThread thread, long startSeq) 
       if (thread == null) 
           throw new SecurityException("Invalid application interface");
       
       synchronized (this) 
           int callingPid = Binder.getCallingPid();
           final int callingUid = Binder.getCallingUid();
           final long origId = Binder.clearCallingIdentity();
           attachApplicationLocked(thread, callingPid, callingUid, startSeq);
           Binder.restoreCallingIdentity(origId);
       
    
 private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) 
        ...
        
          
            mAtmInternal.preBindApplication(app.getWindowProcessController());
            final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
            if (app.isolatedEntryPoint != null) 
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
             else if (instr2 != null) 
                thread.bindApplication(processName, appInfo, providers,
                        instr2.mClass,
                        profilerInfo, instr2.mArguments,
                        instr2.mWatcher,
                        instr2.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
             else 
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
            
            if (profilerInfo != null) 
                profilerInfo.closeFd();
                profilerInfo = null;
            

            // Make app active after binding application or client may be running requests (e.g
            // starting activities) before it is ready.
            app.makeActive(thread, mProcessStats);
            checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
            mProcessList.updateLruProcessLocked(app, false, null);
            checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
         catch (Exception e) 
            // todo: Yikes!  What should we do?  For now we will try to
            // start another process, but that could easily get us in
            // an infinite loop of restarting processes...
            Slog.wtf(TAG, "Exception thrown during bind of " + app, e);

            app.resetPackageList(mProcessStats);
            app.unlinkDeathRecipient();
            mProcessList.startProcessLocked(app, new HostingRecord("bind-fail", processName));
            return false;
        

        // Remove this record from the list of starting applications.
        mPersistentStartingProcesses.remove(app);
        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                "Attach application locked removing on hold: " + app);
        mProcessesOnHold.remove(app);

        boolean badApp = false;
        boolean didSomething = false;

        // See if the top visible activity is waiting to run in this process...
        if (normalMode) 
            try 
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
             catch (Exception e) 
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            
        

        // Find any services that should be running in this process...
        if (!badApp) 
            try 
                didSomething |= mServices.attachApplicationLocked(app, processName);
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
             catch (Exception e) 
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            
        

        ...

        return true;
     

上面这段内容有两段关键的语句,一是调用了 IApplicationThreadbindApplication方法;二是调用了ActivityTaskManagerInternalattachApplication方法。我们先来看位于ActivityThread中的bindApplication这个调用。

 public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial, AutofillOptions autofillOptions,
                ContentCaptureOptions contentCaptureOptions) 
            ...
            sendMessage(H.BIND_APPLICATION, data);
         

方法的结尾,发送了一条what值为H.BIND_APPLICATION的消息。

我们去Handler中找到这条消息的代码段。

 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; 
 private void handleBindApplication(AppBindData data) 
        // Register the UI Thread as a sensitive thread to the runtime.
        ...

        
        Application app;
      
        try 
            //在这里创建了Application对象
            app = data.info.makeApplication(data.restrictedBackupMode, null);

            // Propagate autofill compat state
            app.setAutofillOptions(data.autofillOptions);

            // Propagate Content Capture options
            app.setContentCaptureOptions(data.contentCaptureOptions);

            mInitialApplication = app;

            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) 
                if (!ArrayUtils.isEmpty(data.providers)) 
                    installContentProviders(app, data.providers);
                
            

            // Do this after providers, since instrumentation tests generally start their
            // test thread at this point, and we don't want that racing.
            try 
                mInstrumentation.onCreate(data.instrumentationArgs);
            
            catch (Exception e) 
                throw new RuntimeException(
                    "Exception thrown in onCreate() of "
                    + data.instrumentationName + ": " + e.toString(), e);
            
            try 
                //在这里调用了Application onCreate方法
                mInstrumentation.callApplicationOnCreate(app);
             catch (Exception e) 
                if (!mInstrumentation.onException(app, e)) 
                    throw new RuntimeException(
                      "Unable to create application " + app.getClass().getName()
                      + ": " + e.toString(), e);
                
            
         finally 
            // If the app targets < O-MR1, or doesn't change the thread policy
            // during startup, clobber the policy to maintain behavior of b/36951662
            if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
                    || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) 
                StrictMode.setThreadPolicy(savedPolicy);
            
        

        // 加载字体资源
        FontsContract.setApplicationContextForResources(appContext);
        if (!Process.isIsolated()) 
            try 
                final ApplicationInfo info =
                        getPackageManager().getApplicationInfo(
                                data.appInfo.packageName,
                                PackageManager.GET_META_DATA /*flags*/,
                                UserHandle.myUserId());
                if (info.metaData != null) 
                    final int preloadedFontsResource = info.metaData.getInt(
                            ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
                    if (preloadedFontsResource != 0) 
                        data.info.getResources().preloadFonts(preloadedFontsResource);
                    
                
             catch (RemoteException e) 
                throw e.rethrowFromSystemServer();
            
        
     

app = data.info.makeApplication(data.restrictedBackupMode, null);

这段代码是一段关键代码,它创建了Application以及全局的Application Context对象, 我们深入往下看一下:

源码位置为 frameworks/base/core/java/android/app/LoadedApk.java

 public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) 
        if (mApplication != null) 
            return mApplication;
        

        Application app = null;

        //如果manifest application标签的name属性指定了application类,则使用指定的类,否则默认使用android.app.Application
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) 
            appClass = "android.app.Application";
        

        try 
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) 
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            
            //创建全局的Application Context
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //创建Application对象
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
         catch (Exception e) 
            if (!mActivityThread.mInstrumentation.onException(app, e)) 
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            
        
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        if (instrumentation != null) 
            try 
                instrumentation.callApplicationOnCreate(app);
             catch (Exception e) 
                if (!instrumentation.onException(app, e)) 
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                
            
        

        // Rewrite the R 'constants' for all library apks.
        SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
        final int N = packageIdentifiers.size();
        for (int i = 0; i < N; i++) 
            final int id = packageIdentifiers.keyAt(i);
            if (id == 0x01 || id == 0x7f) 
                continue;
            

            rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
        

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        return app;
     
 static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException 
        Application app = (Application)clazz.newInstance();
        //在这里将applicationContext设置到application对象中
        app.attach(context);
        return app;
     

第一阶段,Application的创建与初始化已经至此结束,接下来我们将目光放到ActivityTaskManagerInternalattachApplication方法。

 public boolean attachApplication(WindowProcessController wpc) throws RemoteException 
            synchronized (mGlobalLockWithoutBoost) 
                return mRootActivityContainer.attachApplication(wpc);
            
         

进入了RootActivityContainer中继续执行。

 boolean attachApplication(WindowProcessController app) throws RemoteException 
        final String processName = app.mName;
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) 
            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
            final ActivityStack stack = display.getFocusedStack();
            if (stack != null) 
                stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
                final ActivityRecord top = stack.topRunningActivityLocked();
                final int size = mTmpActivityList.size();
                for (int i = 0; i < size; i++) 
                    final ActivityRecord activity = mTmpActivityList.get(i);
                    if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
                            && processName.equals(activity.processName)) 
                        try 
                            if (mStackSupervisor.realStartActivityLocked(activity, app,
                                    top == activity /* andResume */, true /* checkConfig */)) 
                                didSomething = true;
                            
                         catch (RemoteException e) 
                            Slog.w(TAG, "Exception in new application when starting activity "
                                    + top.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        
                    
                
            
        
        if (!didSomething) 
            ensureActivitiesVisible(null, 0, false /* preserve_windows */);
        
        return didSomething;
     

ActivityStackSupervisorrealStartActivityLocked方法去真正准备启动Activity。

 boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException 

        ...

        try 
            ...

            try 
               ...


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

                final DisplayContent dc = r.getDisplay().mDisplayContent;
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                        r.icicle, r.persistentState, results, newIntents,
                        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                                r.assistToken));

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

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

               ...

             catch (RemoteException e) 
               ...
            
         finally 
            endDeferResume();
        
 
        ...

        return true;
     

为了解释清楚上述过程,我们必须先得认识一下ClientTransaction及其一系列相关的类。

相关联的类有以下几个:ClientTransactionTransactionExecutorClientLifecycleManager以及LaunchActivityItem,我们一个一个来分析。


LaunchActivityItem LaunchActivityItem实现了BaseClientRequestinterface。这个接口里定义了三个十分重要的方法。

  • preExecute 在请求前进行预处理
  • execute 执行请求
  • postExecute 执行请求后的后续处理

这种设计方式是不是很眼熟!AsyncTask也是基于这种模式设计的,各位读者不妨自行联想类比一下。

LaunchActivityItem这个类设计的目的是什么呢?从名字上来讲,我们很容易想到,它主要的作用就是用来启动一个Activity的,具体反应在它重载的excute方法。

 @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) 
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client, mAssistToken);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     

看到这句话了么,client.handleLaunchActivity(r, pendingActions, null /* customIntent */);client这个对象是什么?我们可以翻阅一下代码的调用链,可以发现client是一个ActivityThread对象,它最终调用的是ActivityThread中的handleLaunchActivity方法。

除了LauncherActivityItem以外,我们还有abstract的ActivityLifecycleItem类,在这个类中定义了一系列的生命周期状态,具体如下:

public static final int UNDEFINED = -1;
 public static final int PRE_ON_CREATE = 0;
 public static final int ON_CREATE = 1;
 public static final int ON_START = 2;
 public static final int ON_RESUME = 3;
 public static final int ON_PAUSE = 4;
 public static final int ON_STOP = 5;
 public static final int ON_DESTROY = 6;
 public static final int ON_RESTART = 7; 

这些状态的值基本按照Activity的生命周期的顺序,以1为步长递增定义。为什么这么设计,我们后续会讲到。

除此之外,系统还定义了StopActivityItemNewIntentItemDestroyActivityItem等等一系列类似的类,这些类都是为了实现具体的和Activity生命周期有关的任务,并按照 预处理——执行——事后处理 的模板编写业务。

除此之外,这些类其中有一部分还有一个作用,就是确定客户端在执行事务后最终应处于的生命周期状态。

ClientLifecycleManager

生命周期管理类,它能够组合多个客户端生命周期变换的请求或回调事务,并将它们作为单个事务执行。这个方法里的内容非常简单,我们主要来关注一下它的scheduleTransaction的方法。

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

根据上述源码,可以看出它调用了传入的ClientTransactionschedule方法。

ClientTransaction

ClientTransaction是一个保存可以发送到客户端的消息序列的容器。它包含了三个比较重要的方法, setLifecycleStateRequestaddCallbackschedule,分别用于设置目标生命周期状态和事务方法,以及执行事务。

我们来看一下schedule这个方法:

public void schedule() throws RemoteException 
     mClient.scheduleTransaction(this);
  

代码的内容非常简单,它将schedule的操作重新分发给了mClient变量,这里的mClient,指的是ActivityThread实例。

public void executeTransaction(ClientTransaction transaction) 
        transaction.preExecute(this);
        getTransactionExecutor().execute(transaction);
        transaction.recycle();
     

这里首先调用了这样一条语句,transaction.preExecute(this),用于执行事务前的预处理操作。

 public void preExecute(android.app.ClientTransactionHandler clientTransactionHandler) 
        if (mActivityCallbacks != null) 
            final int size = mActivityCallbacks.size();
            for (int i = 0; i < size; ++i) 
                mActivityCallbacks.get(i).preExecute(clientTransactionHandler, mActivityToken);
            
        
        if (mLifecycleStateRequest != null) 
            mLifecycleStateRequest.preExecute(clientTransactionHandler, mActivityToken);
        
     

可以看到,它实际调用了通过setLifecycleStateRequestaddCallback两个方法设置进来的对象的preExecute方法。在实际Activity启动流程中,对应的是LaunchActivityItemResumeActivityItem两个类的preExecute方法。

TransactionExecutor

TransactionExecutor是负责管理事务以正确的顺序执行的类。

 public void execute(ClientTransaction transaction) 
        ...

        executeCallbacks(transaction);

        executeLifecycleState(transaction);
        mPendingActions.clear();
     

它首先会通过executeCallbacks方法,执行ClientTransactionadd的所有Callback的executepostExecute方法,具体如下:

 public void executeCallbacks(ClientTransaction transaction) 
       ...
       
       //获取目标生命周期状态
        final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
        final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
                : UNDEFINED;
        // Index of the last callback that requests some post-execution state.
        final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);

        final int size = callbacks.size();
        for (int i = 0; i < size; ++i) 
           ...
           
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
            
            ...
        
     

让我们回到Activity的启动流程的代码中,clientTransaction加入了一个Callback————LaunchActivityItem,从上文可以知,这个类的execute方法里有这么一段代码client.handleLaunchActivity(r, pendingActions, null /* customIntent */);,去负责启动Activity。

executeLifecycleState方法呢?

 private void executeLifecycleState(ClientTransaction transaction) 
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        
      ...

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

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

我们重点关注一下cycleToPath方法:

 private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
            ClientTransaction transaction) 
        final int start = r.getLifecycleState();
        if (DEBUG_RESOLVER) 
            Slog.d(TAG, tId(transaction) + "Cycle activity: "
                    + getShortActivityName(r.token, mTransactionHandler)
                    + " from: " + getStateName(start) + " to: " + getStateName(finish)
                    + " excludeLastState: " + excludeLastState);
        
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
        performLifecycleSequence(r, path, transaction);
     

mHelper.getLifecyclePath(start, finish, excludeLastState):根据当前Activity所处的状态与目标生命周期状态,生成一个包含该状态区间内所有状态的Int数组。

 private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
            ClientTransaction transaction) 
        final int size = path.size();
        for (int i = 0, state; i < size; i++) 
            state = path.get(i);
            if (DEBUG_RESOLVER) 
                Slog.d(TAG, tId(transaction) + "Transitioning activity: "
                        + getShortActivityName(r.token, mTransactionHandler)
                        + " to state: " + getStateName(state));
            
            switch (state) 
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, 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);
            
        
     

performLifecycleSequence开始负责按顺序执行IntArray区间里的状态变换。


让我们重新回到Activity的启动流程上,从handleLaunchActivity继续往下追踪:

 public Activity handleLaunchActivity(ActivityClientRecord r,
      ...
        final Activity a = performLaunchActivity(r, customIntent);
      ...
     

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) 
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) 
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        

        ComponentName component = r.intent.getComponent();
        if (component == null) 
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        

        if (r.activityInfo.targetActivity != null) 
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try 
            java.lang.ClassLoader cl = appContext.getClassLoader();
            //通过newInstance创建Activity实例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) 
                r.state.setClassLoader(cl);
            
         catch (Exception e) 
            if (!mInstrumentation.onException(activity, e)) 
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            
        

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

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) 
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) 
                    config.updateFrom(r.overrideConfig);
                
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) 
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                
                appContext.setOuterContext(activity);
                //调用attach方法,开始初始化Activity
                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,
                        r.assistToken);

                if (customIntent != null) 
                    activity.mIntent = customIntent;
                
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) 
                    activity.setTheme(theme);
                

                activity.mCalled = false;
                if (r.isPersistable()) 
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                 else 
                    //调用Activity的onCreate方法
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                
                if (!activity.mCalled) 
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                
                r.activity = activity;
            
            r.setState(ON_CREATE);

            // updatePendingActivityConfiguration() reads from mActivities to update
            // ActivityClientRecord which runs in a different thread. Protect modifications to
            // mActivities to avoid race.
            synchronized (mResourcesManager) 
                mActivities.put(r.token, r);
            

         catch (SuperNotCalledException e) 
            throw e;

         catch (Exception e) 
            if (!mInstrumentation.onException(activity, e)) 
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            
        

        return activity;
     

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

有些读者可能会对这句话有些疑问,前面不是已经创建过Application对象了吗,怎么这里还调用一遍,不是说一个进程里只能有一个Application对象吗?

我们进入makeApplication方法里看一下,第一句话就解释了原因:

 if (mApplication != null) 
            return mApplication;
         

所以说,并不会重复创建,这里只是将之前已创建的Application重新获取一下而已。

mInstrumentation.callActivityOnCreate(activity, r.state);语句的调用,标识着Activity进入onCreate流程,接下来便是Ui的绘制与展示的流程,在此便不做展开分析了。

文章的最后,我们用一个简单的图表对这一篇activity的启动流程做一个总结,并留给各位读者一个面试中高频次问题:请简述一下Activity的启动流程? 看看各位读者能不能总结归纳出一个比较好的答案。

[ActivityThread.java]
main()
attach()
   |
[ActivityManagerService.java]
attachApplication()
attachApplicationLocked()
	|		 |
	|	[ActivityThread.java]	
	|	 bindApplication()			//发送了H.BIND_APPLICATION消息
	|      handleBindApplication()	                //创建Application实例,并调用onCreate方法
	|                 |
	|	  [LoadedApk.java]
	|	  makeApplication()
[ActivityTaskManagerService.java]
attachApplication()
	|
[RootActivityContainer.java]
attachApplication()
	|
[ActivityStackSupervisor.java]
realStartActivityLocked()
	|
[ClientLifecycleManager.java]
scheduleTransaction()
	|
[ClientTransaction.java]
schedule()
	|
[ActivityThread.java]
executeTransaction()
	|
[TransactionExecutor.java]
execute()
executeCallbacks()
	|	|
	|	cycleToPath()		        //根据当前Activity所处的状态与目标生命周期状态,生成一个包含该状态区间内所有状态的Int数组
	|	performLifecycleSequence()	//开始负责按顺序执行IntArray区间里的状态变换
[LaunchActivityItem.java]	
execute()
	|
[ActivityThread.java]
handleLaunchActivity()
performLaunchActivity()			        //创建Activity实例,调用activity attach和onCreate方法 

文末

我总结了一些Android核心知识点,以及一些最新的大厂面试题、知识脑图和视频资料解析。

需要的直接点击文末小卡片可以领取哦!我免费分享给你,以后的路也希望我们能一起走下去。(谢谢大家一直以来的支持,需要的自己领取)

Android学习PDF+架构视频+面试文档+源码笔记

部分资料一览:

  • 330页PDF Android学习核心笔记(内含8大板块)

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

  • Android BAT大厂面试题(有解析)

领取地址:

以上是关于Android 10 App启动分析之Activity启动篇的主要内容,如果未能解决你的问题,请参考以下文章

AndroidFramework 之启动 ServiceManager

Android 启动过程Activity 启动源码分析 ( ActivityThread -> Activity主线程阶段 一 )

Android App优化之ANR详解

Android四大组件之Service

Android之dropbox 分析

Android性能优化系列之App启动优化