StartActivity路上的mParent

94me發表於2017-10-18

原始碼基於API26

mParent幹嘛來著,帶著這個疑問上車了

通過原始碼發現在Activity中attach()方法中賦值了,事實上還有個方法也可以賦值,即setParent(Activity parent).
不多說直接看attach()

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window) {
    ...
    mMainThread = aThread;
    mInstrumentation = instr;
    mToken = token;
    mIdent = ident;
    mApplication = application;
    mIntent = intent;
    mReferrer = referrer;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    mTitle = title;
    //在這裡被賦值了
    mParent = parent;
    mEmbeddedID = id;
    ...
}複製程式碼

在上面發現,哎呀這個parent也是個Activity啊,那這個mParent就是當前activity的父activity
那什麼時候會執行attach()呢,熟悉activity啟動流程的同學知道在ActivityThread中performLaunchActivity()中執行的

不熟悉的往這裡看原始碼探探之StartActivity(一)

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            ...
            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.parent即是我們的mParent,而r為ActivityClientRecord類,activity的一個記錄類,記錄了很多啟動activity的資訊,我們先不管,我們直接去找哪裡執行了performLaunchActivity()就行。
熟悉activity啟動的會知道,會在handleLaunchActivity()中執行,handleLauchActivity()的ActivityClientRecord也是由上一個類傳過來的,繼續往上,發現在scheduleLaunchActivity()中新建了ActivityClientRecord類的例項,但是,找不到r.parent被賦值,也就是StartActivity跟這個沒半毛錢關係,那我不白寫了嗎

作為屌絲程式設計師就不想去發現這個mParent是個啥嗎

回到最後出現r.parent的地方performLauchActivity(),發現還有一個地方執行了這個方法

public final Activity startActivityNow(Activity parent, String id,
    Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
    Activity.NonConfigurationInstances lastNonConfigurationInstances) {
    ActivityClientRecord r = new ActivityClientRecord();
        r.token = token;
        r.ident = 0;
        r.intent = intent;
        r.state = state;
        //眼睛往這裡
        r.parent = parent;
        r.embeddedID = id;
        r.activityInfo = activityInfo;
        r.lastNonConfigurationInstances = lastNonConfigurationInstances;
    if (localLOGV) {
        ComponentName compname = intent.getComponent();
        String name;
        if (compname != null) {
            name = compname.toShortString();
        } else {
            name = "(Intent " + intent + ").getComponent() returned null";
        }
        Slog.v(TAG, "Performing launch: action=" + intent.getAction()
                + ", comp=" + name
                + ", token=" + token);
    }
    return performLaunchActivity(r, null);
}複製程式碼

找到了吧,賦值了吧,在這裡新建了ActivityClientRecord,並賦值了r.parent
在棄用了的LocalActivityManager類的moveToState方法中有執行

private void moveToState(LocalActivityRecord r, int desiredState) {
        ...
        r.activity = mActivityThread.startActivityNow(
                mParent, r.id, r.intent, r.activityInfo, r, r.instanceState, instance);
        ...
}複製程式碼

這裡有用到了mParent,現在看看LocalActivityManager

public LocalActivityManager(Activity parent, boolean singleMode) {
    mActivityThread = ActivityThread.currentActivityThread();
    mParent = parent;
    mSingleMode = singleMode;
}複製程式碼

這裡的mParent是通過例項化LocalActivityManger賦值的,由於LocalActivityManger已經棄用了,那以前LocalActivityManger幹嘛用的

Create a new LocalActivityManager for holding activities running within the given <var>parent</var>.複製程式碼

只能用蹩腳的英語翻譯一波,也就是管理持有一個執行於給定父activity中的activity
通俗一點就是,管理子activity
從我學習android開始就沒有用過這個東東,這類情況好像跟fragment類似,應該是被fragment取代了,然後就被棄用了
其實在TabActivity中才會出現這種情況,也會用到LocalActivityManger來管理Activity,由於已經棄用了我就不分析了,感興趣自行分析。
本文,只分析了mParent在StartActivity中的作用,結論是半毛線關係都沒有,一直為空

相關文章