Fragment 生命週期怎麼來的?
前言
Fragment對於 Android 開發者來說一點都不陌生,因為幾乎任何一款 app 都大量使用 Fragment,所以 Fragment 的生命週期相信對於大家來說應該都非常清楚,但絕大部分人對於其生命週期都停留在表象,知道一個 Fragment 從建立到執行再到銷燬所要經過的過程,但卻不知道內部如何實現。也許有人會這樣說,給你一輛摩托車,你只要會騎就行,不需要拆開來看它內部的組成結構;對於這樣的問題,我只想說,程式設計不僅學開車,還要學會造車,並且通過了解實現原理,可以讓我們更加清晰的理解 Fragment的生命週期,往往我們通過理解來掌握的東西,是不易忘記的。
Fragment 生命週期流程圖
好了,來看下面流程圖來回顧一下 Fragment 的生命週期
分析
要分析 Fragment 的生命週期,離不開這四個類
FragmentActivity.java
FragmentManager.java
Fragment.java
BackStackRecord.java
啟動 app 首先啟動的是FragmentActivity,我們就從它開始看起,在 onCreate()方法中
@Override
protected void onCreate(Bundle savedInstanceState) {
//Fragment管理類繫結 Activity
mFragments.attachActivity(this, mContainer, null);
// Old versions of the platform didn't do this!
if (getLayoutInflater().getFactory() == null) {
getLayoutInflater().setFactory(this);
}
super.onCreate(savedInstanceState);
NonConfigurationInstances nc = (NonConfigurationInstances)
getLastNonConfigurationInstance();
if (nc != null) {
mAllLoaderManagers = nc.loaders;
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
}
mFragments.dispatchCreate();
}
這裡的mFragments就是FragmentManager,onCreate 中主要做了兩件事,一、把FragmentManager和 Activity繫結,二、 向 Fragment分發 OnCreate 方法mFragments.dispatchCreate();看到這裡,不知道大家有沒有疑問,這裡就會執行 Fragment 的onAttach 和 onCreate 方法嗎?答案顯然是錯誤的,因為我們都知道我們在執行 add + commit的時候才會執行,那麼這裡的 attach 和 onCreate 做了什麼事?進去看看
public void attachActivity(FragmentActivity activity,
FragmentContainer container, Fragment parent) {
if (mActivity != null) throw new IllegalStateException("Already attached");
mActivity = activity;
mContainer = container;
mParent = parent;
}
以上程式碼,只是對變數的賦值,所以不會觸發 Fragment 中的方法。
public void dispatchCreate() {
mStateSaved = false;
moveToState(Fragment.CREATED, false);
}
貌似觸發了 Fragment 中的 onCreate方法,繼續看看;
void moveToState(int newState, int transit, int transitStyle, boolean always) {
//...省略部分程式碼
mCurState = newState;
if (mActive != null) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
moveToState(f, newState, transit, transitStyle, false);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
//...省略部分程式碼
}
這裡有個一判斷if (mActive != null),因為我們目前還沒有地方初始化它,所以這裡顯然不成立,所以 dispatchCreate 方法也沒有觸發Fragment 中的任何方法,但是這裡有一個需要注意
mCurState = newState;
也就是說當前狀態變成了 Fragment.CREATED
FragmentActivity 中的其他方法如 onStart、onResume 都跟 onCreate 方法一樣,都沒有觸發 Fragment 中的方法,
但mCurState 確發生了改變,變成了最後一個狀態的值—> Fragment.RESUMED;
此時 Activity 已經啟動了, FragmentManager中的mCurState也已經是Fragment.RESUMED,我們都知道,當我們通過FragmentManager.beginTransaction().add().commit()這時才是正在啟動一個 Fragment,通過跟蹤程式碼,commit最終呼叫的程式碼如下
public void run() {
//....省略很多程式碼
while (op != null) {
switch (op.cmd) {
case OP_ADD: {
//add 會走這裡
Fragment f = op.fragment;
f.mNextAnim = enterAnim;
mManager.addFragment(f, false);
} break;
case OP_REPLACE: {
//...省略
} break;
case OP_REMOVE: {
//...省略
} break;
case OP_HIDE: {
//...省略
} break;
case OP_SHOW: {
//...省略
} break;
case OP_DETACH: {
//...省略
} break;
case OP_ATTACH: {
//...省略
} break;
default: {
//...省略
}
}
op = op.next;
}
//最後會去改變狀態,這裡就是整個生命週期執行的關鍵程式碼
mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
}
上面程式碼很長,省略了部分程式碼,僅顯示關鍵程式碼,當我們在 add 和 commit 之後,Fragment 會執行mManager.addFragment(f, false);這個方法
if (mAvailIndices == null || mAvailIndices.size() <= 0) {
if (mActive == null) {
mActive = new ArrayList<Fragment>();
}
f.setIndex(mActive.size(), mParent);
mActive.add(f);
} else {
//...省略
}
我們在前面就已經講過了這個if (mActive == null) ,它是在這裡初始化的,所以當我們再次執行
moveToState(int newState, int transit, int transitStyle, boolean always)
的時候,這裡是可以通過的,在 commit 之後就有這樣一段程式碼
//最後會去改變狀態,這裡就是整個生命週期執行的關鍵程式碼
mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);
還記得mCurState的狀態是什麼嗎?沒錯,就是我們前面分析的
mCurState = Fragment.RESUMED;
接下來就來看看 他是怎麼moveToState
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
//...省略
if (f.mState < newState) {
//...省略
}
switch (f.mState) {
case Fragment.INITIALIZING:
//...省略
f.mCalled = false;
f.onAttach(mActivity);
//...省略
if (f.mParentFragment == null) {
mActivity.onAttachFragment(f);
}
if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
}
f.mRetaining = false;
//...省略
}
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
container = (ViewGroup)mContainer.findViewById(f.mContainerId);
if (container == null && !f.mRestored) {
throwException(new IllegalArgumentException(
"No view found for id 0x"
+ Integer.toHexString(f.mContainerId) + " ("
+ f.getResources().getResourceName(f.mContainerId)
+ ") for fragment " + f));
}
}
f.mContainer = container;
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView = NoSaveStateFrameLayout.wrap(f.mView);
if (container != null) {
Animation anim = loadAnimation(f, transit, true,
transitionStyle);
if (anim != null) {
f.mView.startAnimation(anim);
}
container.addView(f.mView);
}
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
f.mInnerView = null;
}
}
f.performActivityCreated(f.mSavedFragmentState);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
case Fragment.ACTIVITY_CREATED:
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.performStart();
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.mResumed = true;
f.performResume();
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
f.performPause();
f.mResumed = false;
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
f.performStop();
}
case Fragment.STOPPED:
if (newState < Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f);
f.performReallyStop();
}
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
if (f.mView != null) {
// Need to save the current view state if not
// done already.
if (!mActivity.isFinishing() && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
f.performDestroyView();
if (f.mView != null && f.mContainer != null) {
Animation anim = null;
if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
anim = loadAnimation(f, transit, false,
transitionStyle);
}
if (anim != null) {
final Fragment fragment = f;
f.mAnimatingAway = f.mView;
f.mStateAfterAnimating = newState;
anim.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
if (fragment.mAnimatingAway != null) {
fragment.mAnimatingAway = null;
moveToState(fragment, fragment.mStateAfterAnimating,
0, 0, false);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
});
f.mView.startAnimation(anim);
}
f.mContainer.removeView(f.mView);
}
f.mContainer = null;
f.mView = null;
f.mInnerView = null;
}
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (mDestroyed) {
if (f.mAnimatingAway != null) {
// The fragment's containing activity is
// being destroyed, but this fragment is
// currently animating away. Stop the
// animation right now -- it is not needed,
// and we can't wait any more on destroying
// the fragment.
View v = f.mAnimatingAway;
f.mAnimatingAway = null;
v.clearAnimation();
}
}
if (f.mAnimatingAway != null) {
// We are waiting for the fragment's view to finish
// animating away. Just make a note of the state
// the fragment now should move to once the animation
// is done.
f.mStateAfterAnimating = newState;
newState = Fragment.CREATED;
} else {
if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
if (!f.mRetaining) {
f.performDestroy();
}
f.mCalled = false;
f.onDetach();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onDetach()");
}
if (!keepActive) {
if (!f.mRetaining) {
makeInactive(f);
} else {
f.mActivity = null;
f.mParentFragment = null;
f.mFragmentManager = null;
f.mChildFragmentManager = null;
}
}
}
}
}
}
f.mState = newState;
}
程式碼很多,也比較亂,這裡我來簡單分析一下,首先的知道這幾種狀態值的大小
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.
現在是f.mState = Fragment.INITIALIZING,newState = RESUMED;
所以if (f.mState < newState)成立,特別注意在上面的程式碼中每一個 case 語句後面都沒有 break 關鍵字,
所以簡化以後的程式碼是:
switch (f.mState) {
case Fragment.INITIALIZING:
f.onAttach(mActivity);
if (f.mParentFragment == null) {
mActivity.onAttachFragment(f);
}
f (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
}
case Fragment.CREATED:
f.performCreateView(...)
f.onViewCreated(...)
f.performActivityCreated(...);
f.restoreViewState(...)
case Fragment.ACTIVITY_CREATED:
case Fragment.STOPPED:
f.performStart();
case Fragment.STARTED:
f.performResume();
以上就是 Fragment 啟動的全過程。看完啟動,再來看看 Fragment 銷燬的過程執行 remove().commit()之後會執行如下程式碼
case OP_REMOVE: {
Fragment f = op.fragment;
f.mNextAnim = exitAnim;
mManager.removeFragment(f, transition, transitionStyle);
} break;
public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
final boolean inactive = !fragment.isInBackStack();
if (!fragment.mDetached || inactive) {
if (mAdded != null) {
mAdded.remove(fragment);
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
fragment.mRemoving = true;
moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
transition, transitionStyle, false);
}
}
可以看到最後一句,就是改變狀態的呼叫,並且把newState 變為
Fragment.INITIALIZING或者Fragment.CREATED,如果當前 Fragment 在前臺臺執行,則為Fragment.INITIALIZING,我們假設當前值為Fragment.INITIALIZING,也就是當前執行的 Fragment 為我們所要移除的 Fragment;
因為if (f.mState < newState)不成立了,所以將會執行以下程式碼
else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
f.performPause();
case Fragment.STARTED:
f.performStop();
case Fragment.STOPPED:
f.performReallyStop();
case Fragment.ACTIVITY_CREATED:
saveFragmentViewState(f);
f.performDestroyView();
case Fragment.CREATED:
f.performDestroy();
f.onDetach();
千萬不要被Fragment.CREATED這樣的命名給疑惑了,,雖然這裡寫的是Fragment.CREATED,但它執行的確實performDestroy()
總結:
仔細分析就會發現整個生命週期其實很簡單,簡單來講,就是 addView 和 removeView 的過程,只是在其中加入了其他類似 Activity 的 onStart 等方法。最後大家可以結合原始碼再看一遍!