Activity與Fragment生命周期的一些觀察和思考

Activity與Fragment的生命周期是一個(gè)老生常談的話題,網(wǎng)上最常見的圖是這個(gè):


fragment1.png

還有這個(gè):


fragment2.png

但是這個(gè)圖并沒有說明Activity和Fragment的每個(gè)階段下,是Fragment的方法先調(diào)用還是Activity的方法先調(diào)用。于是我嘗試了探究了一下。

場(chǎng)景一

我的代碼如下:
Activity1.java

public class Activity1 extends AppCompatActivity {
    FragmentManager fragmentManager;
    FrameLayout frameLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        log("onCreate");
        setContentView(R.layout.activity_simple);
        frameLayout = (FrameLayout) findViewById(R.id.container);
        fragmentManager = getSupportFragmentManager();
         if (savedInstanceState == null) {
            fragmentManager.beginTransaction()
                    .add(R.id.container,SimpleFragment1.getInstance("fragment") , "fragment")
                    .commit();
        }
    }
    @Override
    protected void onStart() {
        super.onStart();
        log("onStart");
        frameLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
    @Override
    protected void onResume() {
        super.onResume();
        log("onResume");
    }
    @Override
    protected void onPause() {
        super.onPause();
        log("onPause");
    }
    @Override
    protected void onStop() {
        super.onStop();
        log("onStop");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        log("onDestroy");
    }
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        log("onSaveInstanceState");
    }
    private void log(String s) {
        Log.i("tag", "Activity1 -- " + s);
    }
}

SimpleFragment1.java

public class SimpleFragment1 extends Fragment {
    private String str;
    private int num=1;
    public SimpleFragment1() {
    }
    public static SimpleFragment1 getInstance(String s) {
        SimpleFragment1 fragment = new SimpleFragment1();
        Bundle b = new Bundle();
        b.putString("string", s);
        fragment.setArguments(b);
        return fragment;
    }
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        log("onAttach");

    }
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        log("onCreate");
    }
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        log("onCreateView");
        str = getArguments().getString("string");
        View v = inflater.inflate(R.layout.fragment_simple, container,false);
        TextView text = (TextView) v.findViewById(R.id.textview);
        text.setText(str);
        return v;
    }
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        log("onActivityCreated");
    }
    @Override
    public void onStart() {
        super.onStart();
        log("onStart");
    }
    @Override
    public void onResume() {
        super.onResume();
        log("onResume");
    }
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        log("onSaveInstanceState");
    }
    @Override
    public void onPause() {
        super.onPause();
        log("onPause");
    }
    @Override
    public void onStop() {
        super.onStop();
        log("onStop");
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        log("onDestroyView");
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        log("onDestroy");
    }
    @Override
    public void onDetach() {
        super.onDetach();
        log("onDetach");
    }
    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        log("isHidden:" + hidden);
    }
    private void log(String s) {
        Log.v("tag","Fragment"+num +" -- " + s);
    }
}

布局:
activity_simple.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>
</LinearLayout>

fragment_simple.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:textSize="20sp" />
</RelativeLayout>

啟動(dòng)Activity時(shí),生命周期函數(shù)調(diào)用如下:


1.png

當(dāng)按鎖屏鍵、 多任務(wù)鍵或者直接按桌面鍵進(jìn)入桌面時(shí),這種情況我暫且稱之為Activity掛起狀態(tài) ,這種情況下生命周期函數(shù)調(diào)用如下:

2掛起.png

當(dāng)Activity從后臺(tái)返回(再次按鎖屏鍵打開屏幕,或從多任務(wù)界面回到當(dāng)前應(yīng)用程序界面)時(shí),這種情況暫且稱為掛起-喚醒 狀態(tài)。生命周期函數(shù)調(diào)用如下:
3掛起_喚醒.png

當(dāng)Activity銷毀時(shí):


4銷毀.png

當(dāng)旋轉(zhuǎn)屏幕時(shí),Activity和Fragment會(huì)被銷毀,然后再重建:


5旋轉(zhuǎn)屏幕.png

注意,上面的場(chǎng)景是,我在Activity的生命周期函數(shù)中super調(diào)用部分之后在打印log的。

場(chǎng)景二

于是我又做了這樣的實(shí)驗(yàn),我將log打印語句放在super之前,我將Activity的代碼改為這樣(其他代碼不變):
Activity2.java

public class Activity2 extends AppCompatActivity {
    FragmentManager fragmentManager;
    FrameLayout frameLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //在super之前打印log
        log("onCreate");       
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);
        frameLayout = (FrameLayout) findViewById(R.id.container);
        fragmentManager = getSupportFragmentManager();
        if (savedInstanceState == null) {
            fragmentManager.beginTransaction()
                    .add(R.id.container,SimpleFragment1.getInstance("fragment") , "fragment")
                    .commit();
        }
    }

    @Override
    protected void onStart() {
        log("onStart");
        super.onStart();
        frameLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
    @Override
    protected void onResume() {
        log("onResume");
        super.onResume();
    }
   @Override
    protected void onPause() {
        log("onPause");
        super.onPause();
    }
    @Override
    protected void onStop() {
        log("onStop");
        super.onStop();
    }
    @Override
    protected void onDestroy() {
        log("onDestroy");
        super.onDestroy();
    }
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        log("onSaveInstanceState");
        super.onSaveInstanceState(outState);

    }
    private void log(String s) {
        Log.i("tag", "Activity2 -- " + s);
    }
}

Activity創(chuàng)建時(shí),生命周期函數(shù)調(diào)用如下:

6創(chuàng)建.png

Activity掛起時(shí):

7掛起.png

注意:與場(chǎng)景一不同,場(chǎng)景一是先打印了Fragment的生命周期函數(shù),再打印了對(duì)應(yīng)Activity的生命周期函數(shù)。在場(chǎng)景二下,是先打印了Activity的onPause再打印Fragment的onPauseonSaveInstanceStateonStop都是先打印了Activity再打印Fragment的。

說明Activity中的這個(gè)super.onXXXX從一定程度上與Fragment的生命周期相關(guān)。后面繼續(xù)分析此處

先看在場(chǎng)景二下,Activity的掛起-喚醒狀態(tài)

8掛起_喚醒.png

Activity的銷毀:


9銷毀.png

旋轉(zhuǎn)屏幕:


10旋轉(zhuǎn)屏幕.png

可以看到,在場(chǎng)景二下,logcat中打印的消息告訴我們,每個(gè)生命周期階段,都是Activity的生命周期函數(shù)先執(zhí)行,然后再執(zhí)行Fragment的。

Activity生命周期中的super.onXXX與Fragment的關(guān)系分析

以Activity1中onCreatesuper.onCreate(savedInstanceState)為例分析:
因?yàn)槲业腁ctivity1繼承自AppCompatActivity,AppCompatActivity的onCreate如下:

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        final AppCompatDelegate delegate = getDelegate();
        delegate.installViewFactory();
        delegate.onCreate(savedInstanceState);
        if (delegate.applyDayNight() && mThemeId != 0) {
            // If DayNight has been applied, we need to re-apply the theme for
            // the changes to take effect. On API 23+, we should bypass
            // setTheme(), which will no-op if the theme ID is identical to the
            // current theme ID.
            if (Build.VERSION.SDK_INT >= 23) {
                onApplyThemeResource(getTheme(), mThemeId, false);
            } else {
                setTheme(mThemeId);
            }
        }
        super.onCreate(savedInstanceState);
    }

在最后又調(diào)用了super.onCreate(savedInstanceState),而AppCompatActivity是繼承自FragmentActivity的,所以可以看出與Fragment一定存在某種聯(lián)系。

FragmentActivity的onCreate

protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);
        super.onCreate(savedInstanceState);
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            mFragments.restoreLoaderNonConfig(nc.loaders);
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);

            // Check if there are any pending onActivityResult calls to descendent Fragments.
            if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) {
                mNextCandidateRequestIndex =
                        savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG);
                int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG);
                String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG);
                if (requestCodes == null || fragmentWhos == null ||
                            requestCodes.length != fragmentWhos.length) {
                    Log.w(TAG, "Invalid requestCode mapping in savedInstanceState.");
                } else {
                    mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length);
                    for (int i = 0; i < requestCodes.length; i++) {
                        mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
                    }
                }
            }
        }
        if (mPendingFragmentActivityResults == null) {
            mPendingFragmentActivityResults = new SparseArrayCompat<>();
            mNextCandidateRequestIndex = 0;
        }
        mFragments.dispatchCreate();
    }

最后一句mFragments.dispatchCreate();,mFragments是一個(gè)FragmentController 。 FragmentController是Activity中所有Fragment的生命周期管理者。其dispatchCreate如下:

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

mFragmentManager是一個(gè)FragmentManagerImpl類的實(shí)例,FragmentManagerImpl繼承自FragmentManager類。這里我們把mFragmentManager看成是Fragment的存放容器就可以了。

dispatchCreate()的實(shí)現(xiàn)如下:

 public void dispatchCreate() {
        mStateSaved = false;
        mExecutingActions = true;
        moveToState(Fragment.CREATED, false);
        mExecutingActions = false;
    }

moveToState()的實(shí)現(xiàn)如下,部分代碼省略:

void moveToState(int newState, boolean always) {
        .......
        mCurState = newState;

        if (mActive != null) {
            boolean loadersRunning = false;
            // Must add them in the proper order. mActive fragments may be out of order
            if (mAdded != null) {
                final int numAdded = mAdded.size();
                for (int i = 0; i < numAdded; i++) {
                    Fragment f = mAdded.get(i);
                    //標(biāo)記處1
                    moveFragmentToExpectedState(f);
                    if (f.mLoaderManager != null) {
                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                    }
                }
            }
            // Now iterate through all active fragments. These will include those that are removed
            // and detached.
            final int numActive = mActive.size();
            for (int i = 0; i < numActive; i++) {
                Fragment f = mActive.get(i);
                if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
                    //標(biāo)記處2
                    moveFragmentToExpectedState(f);
                    if (f.mLoaderManager != null) {
                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                    }
                }
            }
          .......
        }
    }

(在上面代碼片段中我做了兩個(gè)標(biāo)記處,后面接著分析這兩處)
moveToState中又調(diào)用了moveFragmentToExpectedState(),從函數(shù)名可知,實(shí)際做的就是將每個(gè)fragment都轉(zhuǎn)移到各自對(duì)應(yīng)的狀態(tài)。
Fragment定義了如下幾種狀態(tài):
static final int INITIALIZING = 0; // Not yet created.
static final int CREATED = 1; // Created.
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
static final int STOPPED = 3; // Fully created, not started.
static final int STARTED = 4; // Created and started, not resumed.
static final int RESUMED = 5; // Created started and resumed.
初始時(shí)Fragment是位于INITIALIZING 狀態(tài)。

moveFragmentToExpectedState(Fragment f)函數(shù):

void moveFragmentToExpectedState(Fragment f) {
        ....
        moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);

        if (f.mView != null) {
            // Move the view if it is out of order
            Fragment underFragment = findFragmentUnder(f);
            if (underFragment != null) {
                final View underView = underFragment.mView;
                // make sure this fragment is in the right order.
                final ViewGroup container = f.mContainer;
                int underIndex = container.indexOfChild(underView);
                int viewIndex = container.indexOfChild(f.mView);
                if (viewIndex < underIndex) {
                    container.removeViewAt(viewIndex);
                    container.addView(f.mView, underIndex);
                }
            }
           ...
          }
    }

其中調(diào)用了moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive)。moveToState函數(shù)較長(zhǎng),該函數(shù)我把它稱為關(guān)鍵函數(shù)吧,部分代碼省略:

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) {
        // Fragments that are not currently added will sit in the onCreate() state.
        if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
            newState = Fragment.CREATED;
        }
        .....
        if (f.mState < newState) {
            ....
            switch (f.mState) {
                case Fragment.INITIALIZING:
                    ....
            //1.在這里調(diào)用了Fragment的onAttach()
                    f.onAttach(mHost.getContext());
                    ...
                    dispatchOnFragmentAttached(f, mHost.getContext(), false);

                    if (!f.mRetaining) {
            //2.在performCreate內(nèi)部調(diào)用了Fragment的onCreate()
                        f.performCreate(f.mSavedFragmentState);
                        dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
                    } else {
                        f.restoreChildFragmentState(f.mSavedFragmentState);
            //*****注意:這里將Fragment的狀態(tài)設(shè)置為CREATED
                        f.mState = Fragment.CREATED;
                    }
            f.mRetaining = false;
                    if (f.mFromLayout) {
                        //3.在performCreateView中調(diào)用了Fragment的onCreateView()
                        f.mView = f.performCreateView(f.getLayoutInflater(
                                f.mSavedFragmentState), null, f.mSavedFragmentState);
                        if (f.mView != null) {
                            f.mInnerView = f.mView;
                            if (Build.VERSION.SDK_INT >= 11) {
                                ViewCompat.setSaveFromParentEnabled(f.mView, false);
                            } else {
                                f.mView = NoSaveStateFrameLayout.wrap(f.mView);
                            }
                            if (f.mHidden) f.mView.setVisibility(View.GONE);
                            f.onViewCreated(f.mView, f.mSavedFragmentState);
                            dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
                        } else {
                            f.mInnerView = null;
                        }
                    }
                    ....
                case Fragment.CREATED:
                    if (newState > Fragment.CREATED) {
                        if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
                        ....
            //4.在performActivityCreated()中調(diào)用了Fragment的onActivityCreated()
                        f.performActivityCreated(f.mSavedFragmentState);
                        dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
                        if (f.mView != null) {
                            f.restoreViewState(f.mSavedFragmentState);
                        }
                        f.mSavedFragmentState = null;
                    }
                case Fragment.ACTIVITY_CREATED:
                    if (newState > Fragment.ACTIVITY_CREATED) {
                        f.mState = Fragment.STOPPED;
                    }
                case Fragment.STOPPED:
                    if (newState > Fragment.STOPPED) {
                        f.performStart();
                        dispatchOnFragmentStarted(f, false);
                    }
                case Fragment.STARTED:
                    if (newState > Fragment.STARTED) {
                        f.performResume();
                        dispatchOnFragmentResumed(f, false);
                        f.mSavedFragmentState = null;
                        f.mSavedViewState = null;
                    }
            }
        } else if (f.mState > newState) {
            switch (f.mState) {
                case Fragment.RESUMED:
                    if (newState < Fragment.RESUMED) {
                        f.performPause();
                        dispatchOnFragmentPaused(f, false);
                    }
                case Fragment.STARTED:
                    if (newState < Fragment.STARTED) {
                        f.performStop();
                        dispatchOnFragmentStopped(f, false);
                    }
                case Fragment.STOPPED:
                    if (newState < Fragment.STOPPED) {
                        f.performReallyStop();
                    }
                case Fragment.ACTIVITY_CREATED:
                    .....
                case Fragment.CREATED:
                    .....
            }
        }  
    }

該函數(shù)中就是對(duì)Fragment的各種不同的狀態(tài)進(jìn)行處理,一開始Fragment是處于INITIALIZING狀態(tài)的,在INITIALIZING對(duì)應(yīng)的case 語句中,相應(yīng)的調(diào)用了Fragment的onAttach(),onCreate()onCreateView(),我在代碼中也寫了注釋。在調(diào)用了onCreate之后,同時(shí)Fragment的狀態(tài)會(huì)被設(shè)置為CREATED

還記得moveToState(int newState, boolean always)中的標(biāo)記處一和標(biāo)記處二嗎,記不得就再回去看看。這兩處標(biāo)記處都是調(diào)用了關(guān)鍵函數(shù)moveToState。我們可以這么理解,標(biāo)記處一的關(guān)鍵函數(shù)是對(duì)INITIALIZING狀態(tài)的Fragment進(jìn)行處理,當(dāng)執(zhí)行完標(biāo)記處一的關(guān)鍵函數(shù)后,F(xiàn)ragment的狀態(tài)被設(shè)置為CREATED,然后到標(biāo)記處二,對(duì)CREATED狀態(tài)的Fragment再進(jìn)行處理。

下面我們分析關(guān)鍵函數(shù)中對(duì)于CREATED狀態(tài)的case語句:

 case Fragment.CREATED:
                    if (newState > Fragment.CREATED) {            
                        ....
            //在performActivityCreated()中調(diào)用了Fragment的onActivityCreated()
                        f.performActivityCreated(f.mSavedFragmentState);
                        dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
                        if (f.mView != null) {
                            f.restoreViewState(f.mSavedFragmentState);
                        }
                        f.mSavedFragmentState = null;
                    }

performActivityCreated()函數(shù)中,調(diào)用了Fragment的onActivityCreated():

 void performActivityCreated(Bundle savedInstanceState) {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
        }
        mState = ACTIVITY_CREATED;
        mCalled = false;
        onActivityCreated(savedInstanceState);
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onActivityCreated()");
        }
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchActivityCreated();
        }
    }

至此,F(xiàn)ragment的創(chuàng)建過程基本完畢,F(xiàn)ragment的創(chuàng)建時(shí)生命周期函數(shù)可以解釋為:在INITIALIZING中執(zhí)行了onAttach(),onCreate()onCreateView(),在CREATED中執(zhí)行了onActivityCreated()

其他的Fragment生命周期函數(shù)也和上面分析的onCreate類似,其本質(zhì)都是在關(guān)鍵函數(shù)中對(duì)各種狀態(tài)進(jìn)行處理并觸發(fā)生命周期回調(diào)函數(shù)。

總結(jié)

實(shí)際上同階段下Activity的生命周期函數(shù)是Fragment的生命周期函數(shù)入口,這里同階段是指Activity的onCreate對(duì)應(yīng)Fragment的onCreate,Activity的onResume對(duì)應(yīng)Fragment的onResume之類的。

Activity的super.onXXXX中正是調(diào)用了Fragment的生命周期函數(shù)onXXXX。這也就解釋了場(chǎng)景一和場(chǎng)景二中為什么在不同的地方打印log結(jié)果輸出是不一樣的。

關(guān)于Activity與Fragment的生命周期,github上還有一位大神畫了這樣一張圖,地址在這里:https://github.com/xxv/android-lifecycle

其實(shí)我還有一點(diǎn)沒理解,在場(chǎng)景一中,由于我log語句是寫在super之后的,為啥是Activity1的onResume先執(zhí)行,再執(zhí)行Fragment1的onResume?如果有知道的朋友請(qǐng)告訴我,謝謝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容