ソース分析Activityの起動プロセス

5691 ワード

Activityを起動すると、startActivity ForResultによってActivityの起動プロセスが開始されます.

1.startActivity ForResultメソッド(Activity.java)


startActivity ForResultメソッドの重要なメソッドexecStartActivity execStartActivityメソッドはマジックボックスのようなもので、後続の起動プロセスは呼び出し元、パラメータと密接に関連しています.
 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ...
        }
      ...
}

2.execStartActivityメソッド(Instrumentation.java)

  • execStartActivityメソッドでActivityを開始するインプリメンテーションはActivityManagerに渡される.getService()のstartActivityメソッドが完了しました.ActivityManager.getService()が得たのはAMS(Activity Management Service)で、Binderです.
  • でcheckStartActivity Resultメソッドが呼び出され、起動結果
  • がチェックされます.
    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            IApplicationThread whoThread = (IApplicationThread) contextThread;
            ...
            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;
        }
    

    3.この起動プロセスをAMSのstartActivityに移行する


    このメソッドでは、一連のメソッドが呼び出されます.最終的にActivity StackSupervisorのrealStartActivity Lockedメソッドを起動のキーメソッドとし、起動プロセスを継続します.

    4.realStartActivity Lockedメソッド(AMS---->Activity StackSupervisor.java)


    この方法では、このようなコードappを呼び出す.thread.scheduleLaunchActivity()は、AMS側がこのActivityの記録の各方面の情報をパラメータとし、クライアントがActivityの各種情報であるActivity ClientRecordを取得することができる.
  • app.threadは実際にはActivity Threadの内部クラスApplicationThreadである.つまりexecStartActivityメソッドを呼び出して渡すパラメータmMainThread.getApplicationThread()
  • これにより、プロセスは、サービスからクライアントに戻る
  • を開始する.
    //ActivityStack 
    final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
        //...  
        try {
            //...
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration),
                    r.compat, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);
            //...
        } catch (RemoteException e) {
            //...
        }
        //...    
        return true;
    }
    

    5. scheduleLaunchActivity() (ActivityThread.java)


    この方法はActivityに関する情報を保存した後、HというHandlerに起動メッセージを送信し、次にHandler Hは「LAUNCH_ACTIVITY」というメッセージを処理し、handleLaunchActivityメソッドによって実現する.
    //ActivityThread 
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            Bundle state, List pendingResults,
            List pendingNewIntents, boolean notResumed, boolean isForward,
            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
        ActivityClientRecord r = new ActivityClientRecord();
        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;
        r.startsNotResumed = notResumed;
        r.isForward = isForward;
        r.profileFile = profileName;
        r.profileFd = profileFd;
        r.autoStopProfiler = autoStopProfiler;
        updatePendingConfiguration(curConfig);
        queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
    }
    

    6.handleLaunchActivityメソッド(Activity Thread.java)


    H Handlerによってメッセージが処理されることは、開始プロセスがプライマリスレッドに到達することを意味する
  • このメソッドではperformLaunchActivityメソッドが呼び出され、Activityオブジェクトの作成と起動プロセス
  • が最終的に完了します.
      public Activity handleLaunchActivity(ActivityClientRecord r,
                PendingTransactionActions pendingActions, Intent customIntent) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            ...
            final Activity a = performLaunchActivity(r, customIntent);
    
            ...
            return a;
        }
    

    7.performLaunchActivityメソッド(Activity Thread.java)


    以下のことを完成する
  • Activity ClientRecordからActivityコンポーネントを起動する情報
  • を取得する.
  • InstrumentationのnewActivityメソッドを使用してクラスローダを使用してActivityオブジェクトを作成する
  • LoadedApkのmakeApplicationメソッドによりApplicationオブジェクト
  • を作成しようとする.
  • ContextImplオブジェクトを作成し、attachメソッドによって重要なデータの初期化を完了する(attachメソッドContextImplによってActivityに関連付けられる)
  • .
  • Activityを呼び出すonCreateメソッド
  • これで起動プロセス全体が完了しました
  • 新しいActivityが作成されるタイミング
  • ActivityのonCreateメソッドはいつシステムにコールバックされますか?https://www.jianshu.com/p/4edf1987a940