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()
总结:
细致分析就会发现整个生命周期事实上非常easy。简单来讲,就是 addView 和 removeView 的过程,仅仅是在当中增加了其它相似 Activity 的 onStart 等方法。
最后大家能够结合源代码再看一遍!