回顧一下Fragment的生命周期源碼

本篇文章帶讀者走一遍源碼Fragment的前幾個生命周期泡仗,看源碼其實有畫流程圖就不會覺得枯燥。但是寫文章我個人倒是覺得寫這種讀源碼文章挺枯燥的。堪遂。。哈哈哈 (ps:讀者您最好就是開一下IDE萌庆,看源碼跟著這里面的流程走一下溶褪,希望對你自己去看源碼會有點幫助)

Fragment生命周期

  • 首先先看一下官網(wǎng)的生命周期圖。

Activity與Fragment生命周期對照圖

從上面的圖可以明顯看出來Activity的生命周期與Fragment是相掛鉤的践险。
Activity的生命周期是AMS管理,Fragment的生命周期是被所屬Activity管理猿妈。

Fragment相關(guān)類

我們既然要看Fragment的生命周期吹菱,而生命周期是交給Activity管理,且跟Activity的生命周期是相關(guān)的,那我們的切入點就可以從Activity的生命中周期著手彭则。且本片文章所看的源碼是androidx下的FragmentActivity

Activity與Fragment聯(lián)動.png

  • FragmentActivity擁有成員對象FragmentController mFragments
  • FragmentController擁有成員對象FragmentHostCallback mHost
  • FragmentHostCallback 擁有成員對象 FragmentManagerImpl mFragmentManager

每個類對應的責任:

  • FragmentController是控制類鳍刷,對外提供控制Fragment的生命周期等方法,內(nèi)部實現(xiàn)交由FragmentHostCallback中的FragmentManagerImpl去最終實現(xiàn)俯抖。
  • FragmentManagerImpl 是最終處理Fragment所有邏輯的實現(xiàn)類输瓜。
  • FragmentHostCallback這個類中擁有了ActivityContext,FragmentManagerImpl這幾個成員變量芬萍,在創(chuàng)建FragmentController的時候我們需要指定一個FragmentHostCallback實例用于指定FragmentController的宿主尤揣。(這個不理解的話,下面第一個代碼塊中有說到)

這幾個類的關(guān)系簡化起來就是通過組合的形式柬祠,大致就是 FragmentActivity 使用一個FragmentController管理類北戏,由它去操控最終的FragmentManagerImpl控制Fragment的生命周期或者其他相關(guān)的邏輯。

源碼追蹤

先切入主題漫蛔,我們看一下
FragmentActivity類的onCreate()

public class  FragmentActivity{
//mFragments的初始化
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);
        .......
        mFragments.dispatchCreate();
}
//FragmentHostCallback 傳入FragmentActivity作為Fragment的宿主嗜愈。
//并提供了可以獲取到宿主信息的方法。
class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
        @Override
        public FragmentActivity onGetHost() {
            return FragmentActivity.this;
        }
        @Nullable
        @Override
        public View onFindViewById(int id) {
            return FragmentActivity.this.findViewById(id);
        }
}
}

上面代碼部分注釋了莽龟,我們直接看mFragments.dispatchCreate();里面的實現(xiàn)

public class FragmentController {
 private final FragmentHostCallback<?> mHost;

 public void dispatchCreate() {
      mHost.mFragmentManager.dispatchCreate();
    }
}

直接從這里面進去FragmentManagerImpl

final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
    public void dispatchCreate() {
        mStateSaved = false;
        mStopped = false;
        dispatchStateChange(Fragment.CREATED);//關(guān)鍵點1
    }

    private void dispatchStateChange(int nextState) {
         ...省略
         moveToState(nextState, false);//關(guān)鍵點2
         ...省略
    }

    void moveToState(int newState, boolean always) {
          ...省略
        mCurState = newState; //這里的mCurState = Fragment.CREATED
        if (mActive != null) {
            final int numAdded = mAdded.size();
            for (int i = 0; i < numAdded; i++) {
                Fragment f = mAdded.get(i);
                moveFragmentToExpectedState(f);//關(guān)鍵點3
            }
       ...省略
        }
    }
}

這里重點記住 傳入的狀態(tài)mCurState = Fragment.CREATED

  void moveFragmentToExpectedState(Fragment f) {
      ...省略
        int nextState = mCurState;  //mCurState = Fragment.CREATED
        moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false); //關(guān)鍵點1
    }

這里先展示一下Fragment狀態(tài)的對象值芝硬。后面對比用得上。

static final int INITIALIZING = 0;     // Not yet created.
static final int CREATED = 1;          // Created.
static final int ACTIVITY_CREATED = 2; // Fully created, not started.
static final int STARTED = 3;          // Created and started, not resumed.
static final int RESUMED = 4;          // Created started and resumed.

接下來就是最終控制邏輯的方法了轧房。這個方法就是控制Fragment生命周期的邏輯實現(xiàn)拌阴,因為這個方法過于長,我截取必要部分出來奶镶。

//此時
//mState = INITIALIZING
//newState = Fragment.CREATED
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) {
      .......省略
       if (f.mState <= newState){
        switch (f.mState) {//這里的case沒有break迟赃。所以會執(zhí)行所有的case。
         case Fragment.INITIALIZING:
                    if (newState > Fragment.INITIALIZING) {
                    ...省略
                    f.onAttach(mHost.getContext());  //關(guān)鍵點1
                    ...省略
                   if (!f.mIsCreated) {//mIsCreated這個值賦值是在performCreate()厂镇,所以第一次為falese則符合這個條件
                    f.performCreate(f.mSavedFragmentState); //關(guān)鍵點2
                    }
                    }
         case Fragment.CREATED:
                ensureInflatedFragmentView(f);//關(guān)鍵點3
        }
}

關(guān)鍵點1:調(diào)用了Fragment中第一個生命周期onAttach(Context context)

關(guān)鍵點2: 調(diào)用FragmentonCreate方法

 void performCreate(Bundle savedInstanceState) {
       ...省略
        mState = CREATED;
        mCalled = false;
        onCreate(savedInstanceState);//調(diào)用Fragment的onCreate方法
        mIsCreated = true;//上個代碼塊的條件值 mIsCreated的賦值在這里
        ...省略
    }

關(guān)鍵點3: 調(diào)用FragmentonViewCreated方法

 void ensureInflatedFragmentView(Fragment f) {
        if (f.mFromLayout && !f.mPerformedCreateView) {
            f.performCreateView(f.performGetLayoutInflater(
                    f.mSavedFragmentState), null, f.mSavedFragmentState);
            if (f.mView != null) {
                f.mInnerView = f.mView;
                f.mView.setSaveFromParentEnabled(false);
                if (f.mHidden) f.mView.setVisibility(View.GONE);
                f.onViewCreated(f.mView, f.mSavedFragmentState);//調(diào)用Fragment的onViewCreated方法
                dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
            } else {
                f.mInnerView = null;
            }
        }
    }

由上面的流程下來你可以看到纤壁,當Activity執(zhí)行onCreate()的時候,至少Fragment有三個生命周期被調(diào)用到onAttach() ->onCreate()->onCreateView()捺信。
而后的Activity onStart()可以看一下

    protected void onStart() {
        super.onStart();
        if (!mCreated) {
            mCreated = true;
            mFragments.dispatchActivityCreated();//關(guān)鍵1
        }
          mFragments.dispatchStart();//關(guān)鍵2
    }

你可以看到上面兩個調(diào)用分別是 dispatchActivityCreated() dispatchStart()對應Fragment的生命期為 onActivityCreate()Start() 后面的就讀者自己去看一下啦 根據(jù)上面的一樣邏輯思路很容易就看懂的~

總結(jié)

其實這篇文章就是看源碼寫的文章酌媒,看源碼主要就是抓住重點,確定自己的目標要看懂什么找什么迄靠。只要確定這一點然后一邊畫代碼的流水線圖秒咨,很容易就找到代碼的流向。然后根據(jù)看懂了之后再總結(jié)一下這些類的作用掌挚,這樣寫有什么好處雨席。

最后附上一副自己在看源碼的時候畫的圖~


Fragment生命周期邏輯圖片.jpg
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吠式,隨后出現(xiàn)的幾起案子陡厘,更是在濱河造成了極大的恐慌抽米,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糙置,死亡現(xiàn)場離奇詭異云茸,居然都是意外死亡,警方通過查閱死者的電腦和手機谤饭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門查辩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人网持,你說我怎么就攤上這事宜岛。” “怎么了功舀?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵萍倡,是天一觀的道長。 經(jīng)常有香客問我辟汰,道長列敲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任帖汞,我火速辦了婚禮戴而,結(jié)果婚禮上嘉赎,老公的妹妹穿的比我還像新娘写穴。我一直安慰自己,他們只是感情好侠坎,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布催首。 她就那樣靜靜地躺著扶踊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪郎任。 梳的紋絲不亂的頭發(fā)上秧耗,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音舶治,去河邊找鬼分井。 笑死,一個胖子當著我的面吹牛霉猛,可吹牛的內(nèi)容都是我干的尺锚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼韩脏,長吁一口氣:“原來是場噩夢啊……” “哼缩麸!你這毒婦竟也來了铸磅?” 一聲冷哼從身側(cè)響起赡矢,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤杭朱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吹散,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弧械,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年空民,在試婚紗的時候發(fā)現(xiàn)自己被綠了刃唐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡界轩,死狀恐怖画饥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浊猾,我是刑警寧澤抖甘,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站葫慎,受9級特大地震影響衔彻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜偷办,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一艰额、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧椒涯,春花似錦柄沮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至泪喊,卻和暖如春棕硫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背袒啼。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工哈扮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蚓再。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓滑肉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親摘仅。 傳聞我的和親對象是個殘疾皇子靶庙,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容