Activity的啟動過程第二篇

RoyGit發表於2019-03-01

首先,還是先將總體的順序寫出來
1、Laucher元件 首先向AMS(AndroidManagerService)傳送一個啟動Mainactivity的請求, 這個請求是程式間通訊的。
2、AMS首先將要啟動的MainActivity元件的資訊保留起來,然後向Laucher元件傳送一個進入終止狀態的程式通訊。
3、然後,Laucher元件會接收到AMS發來的中止請求,進入中止狀態, 然後再向AMS傳送訊息,告訴AMS 我已經進入中止狀態了,你請繼續做你的是事情,這樣AMS就能繼續進行啟動Aty的操作。
4、由於MainAty的啟動是在Lauther程式中啟動的,Lauther中止了,程式應用程式也就不存在了,然後AMS就會新啟動一個應用程式。
5、新的應用程式啟動後,就會告訴AMS 我(新的應用程式)已經啟動好了,然後發一個通訊請求給AMS。
6、接收到新應用程式發來的通訊後,AMS就會把第二步保留的元件資訊 傳遞給新的程式,然後新的程式就可以靠這些資訊去啟動MainAty。

上一篇啟動過程分析完了第一步,這一篇來分析第二步。也是先放原始碼。

    public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            final View decor = mWindow != null ? mWindow.peekDecorView() : null;
            if (decor != null) {
                decor.cancelPendingInputEvents();
            }
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }


複製程式碼

我們單獨把這段程式碼拿出來分析

        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
複製程式碼

可以看到,這裡面呼叫了Instrument類,並且執行了execStartActivity()這個方法。
我麼先簡單瞭解一下這個Instrument類的作用。
Instrument類的主要作用:他用來監控,應用程式和系統之間的互動操作。
OK,現在可以看一下里面的引數,有一個mMainThread.這個mMainThread是Activity的一個成員變數ActivityThread,系統每開啟一個應用,都會初始化一個ActivityThread的例項,並且傳給每個應用的父親Activity(這個父親Activity就是我們的每一個繼承的Activity),然後看一下mMainThread.getApplicationThread()這個,好的 ,看一下ActivityThread的原始碼裡面這個方法。

   public ApplicationThread getApplicationThread()
    {
        return mAppThread;
    }
複製程式碼

返回的是一個mAppThread,這個Application其實就是一個IBinder的本地物件。有興趣的道友可以看一下原始碼,會呼叫mAppThread.asBinder方法,可以驗證這一點。這個mAppThread物件可以和Launcher通訊,在執行了execStartActivity()之後就會通過binder通知Launcher進入停止狀態。

在這裡,作者羅老師強調了一個地方,就是這個mToken,檢視原始碼知道,這個mToken是個IBinder型別的成員變數,他是一個IBinder的代理物件,指向了,AMS中,一個型別為ActivityRecord的本地物件。每一個啟動的Activity元件,在AMS中都有一個對應的ActivityRecord的物件,這個ActivityRecord物件,是用來維護對應的Activity的執行狀態以及資訊。

到這個地方,第二部就完成了。

OK 繼續深入execStartActivity()這個方法。先看原始碼

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
            //主要過程放在IApplication中執行
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
				//這裡查詢Activity 是否存在
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
			//這裡是真正開啟Activity的地方
			//這個ActivityManagerNative.getDefault()是AMS的代理物件,呼叫startActivity來將activity啟動起來
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }
複製程式碼

我們著重看這段程式碼

			//這裡是真正開啟Activity的地方
			//這個ActivityManagerNative.getDefault()是AMS的代理物件,呼叫startActivity來將activity啟動起來
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
複製程式碼

可以看到,在execStartActivity裡面,呼叫了ActivityManagerNative.getDefault(),那這個ActivityManagerNative.getDefault()返回的是什麼呢?看一下原始碼。

  static public IActivityManager getDefault() {
        return gDefault.get();
    }

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
複製程式碼

這個返回的是一個IActivityManager物件,這個IAM 實際上是AMS(AndroidManagerService)的代理物件,然後通過呼叫它的startActivity來通知AMS將一個Activity元件啟動起來。
第二篇先寫到這裡,一點一點消化。

相關文章