Activity啟動流程分析記錄(Api26)

weixin_33912445發表於2018-01-24

直觀流程圖

2786935-39eefc32ca085048.png
圖1-1 Activity啟動流程

具體流程分析

  1. Activity呼叫startActivity,雖然startActivity有很多過載函式,但是最終也會呼叫Activity中的startActivityForResult方法,在startActivityForResult中有一個mParent的null判斷,mParent代表的是ActivityGroup,ActivityGroup用於在一個Activity中放入多個子Activity,已經被廢棄,使用Fragmemt和FragmentManager替代,所以主要看mParent==null
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            //呼叫Instrumentation的execStartActivity方法
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            //返回結果不為空,證明返回的intent中含有引數,將引數作為結果返回
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
          
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
        } else {
           ....忽略
        }
    }
  1. 在Instrumentation.execStartActivity方法程式碼,具體關注ActivityManager.getService().startActivity方法
 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);

            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options); 
            checkStartActivityResult(result  , intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

上面這段程式碼中,可以發現啟動Activity真正的實現由ActivityManager.getService()的startActivity方法完成,ActivityManager.getService()方法其實是一個IActivityManager型別的Binder物件,這個Binder物件使用一個單例模式進行封裝,保證全域性只有一個IActivityManager物件.
在執行完 ActivityManager.getService().startActivity方法後,還有一句checkStartActivityResult(result , intent);這句程式碼就是用於檢查啟動的Activity的結果,當無法正常啟動Activity的時候,就會丟擲異常,其中最常見的一個異常資訊就是

Unable to find explicit activity class ** have you declared this activity in your AndroidManifest.xml?

  1. 通過上面的流程分析,現在發現具體的Activity啟動主要就是在AMS中的startActivity方法.AMS中的startActivity又呼叫了startActivityAsUser方法,這裡又將Activity的啟動轉移到了ActivityStarter的startActivityMayWait方法中,
  public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }


public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        ...
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }
  1. 饒了一大圈其實就是在ActivityStarter內部,ActivityStack,ActivityStackSupervisor之間不斷呼叫,最終落在ActivityStackSupervisor的realStartActivityLocked方法中,其中注意方法中以下程式碼
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,                    // override configs.
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);

scheduleLaunchActivity這個方法是在realStartActivityLocked中被呼叫的,app.thread物件是IApplicationThread,這個IApplicationThread是一個IBinder物件,這個介面的實現類在ActivityThread中,一個私有的內部類,ApplicationThread ,該類繼承自IApplicationThread.Stub,實現了IApplicationThread所有的抽象方法.

scheduleLaunchActivity就是啟動Activity的方法,通過傳送一個啟動activity的訊息交給handler處理,handler接收到訊息後呼叫handleLaunchActivity方法,然後呼叫了handleResumeActivity方法呼叫被啟動的Activity的onResume生命週期方法.

 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

          ...
            sendMessage(H.LAUNCH_ACTIVITY, r);
}

public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
}

handleLaunchActivity中呼叫了performLaunchActivity和handleResumeActivity方法

  1. 在performLaunchActivity中,通過呼叫了Instrumentation的newActivity方法,通過反射建立了Activity物件,呼叫LoadedApk中的makeApplication建立了Application物件,其內部實現也是通過反射.
 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

忽略部分初始化程式碼...
          //建立Context的實現類
          ContextImpl appContext = createBaseContextForActivity(r);

            //建立Activity物件
            java.lang.ClassLoader cl = appContext.getClassLoader();
            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);
            }

...
            //建立Application物件
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...

//Activity與Context建立聯絡,同時完成Activity與Window的關聯.
 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);


        
}

Activity的啟動流程大體如此,大部分邏輯都是參考<<Android開發藝術探索>>,但是由於書中的原始碼版本是Android5.0,而我在學習的時候使用的原始碼是Android8.0,所以可能會有部分程式碼有出入,但是整體結構和邏輯都是一樣的,並不影響對Activity啟動的掌握

相關文章