如果你已经使用过fragment,我先提出几个问题。
1、按返回键的时候,如果当前的fragment是加入到栈的(其实这个说法不是很准确,因为真正加入栈的是操作fragment的事务),那么这个fragment会被remove掉,而如果没有加入栈,那么回退按键对这个fragment一点反应也没有?
2、加入到栈的fragment在被remove的时候,其生命周期走到onDestroyView而没有走到onDestroy,而没有加入栈的话,会走到onDestroy?
你可以先代码验证如上问题,然后自己寻找答案
下面是我读源码时候的理解;
1、按返回键,本质上是调用popBackStack(….)方法,最终会从事务栈中取出最近的一个事务,然后执行操作,如果当初add这个fragment的时候没有加入栈,当然从中找不到事务,也不会对当前fragment有影响。
部分代码如下:
boolean popBackStackState(Handler handler, String name, int id, int flags) {
if (mBackStack == null) {
return false;
}
if (name == null && id < 0 && (flags&POP_BACK_STACK_INCLUSIVE) == 0) {
int last = mBackStack.size()-1;
if (last < 0) {
return false;
}
//取出最近的事务,BackStackRecord 其实对应的就是 FragmentTransaction
final BackStackRecord bss = mBackStack.remove(last);
SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
if (mCurState >= Fragment.CREATED) {
bss.calculateBackFragments(firstOutFragments, lastInFragments);
}
bss.popFromBackStack(true, null, firstOutFragments, lastInFragments);
reportBackStackChanged();
}
2、加不加入到栈,会什么在remove操作时候,会影响到onDestroy生命周期,这个我们从源码看下,
2.1 先看removeFragment,看我的注释
public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
//此处关键,如果加入栈,inactive 为false,否则为true
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);
}
}
moveToState 方法,从上面传进来的newState,如果加入栈,其值为Fragment.CREATED,否则为Fragment.INITIALIZING
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.mRemoving && newState > f.mState) {
// While removing a fragment, we can't change it to a higher state.
newState = f.mState;
}
// Defer start if requested; don't allow it to move to STARTED or higher
// if it's not already started.
if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
newState = Fragment.STOPPED;
}
if (f.mState < newState) {
// 此处省略......
} 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();
}
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 (mHost.onShouldSaveFragmentState(f) && 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;
final View viewToAnimate = f.mView;
anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener(
viewToAnimate, anim) {
@Override
public void onAnimationEnd(Animation animation) {
super.onAnimationEnd(animation);
if (fragment.mAnimatingAway != null) {
fragment.mAnimatingAway = null;
moveToState(fragment, fragment.mStateAfterAnimating,
0, 0, false);
}
}
});
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();
} else {
f.mState = Fragment.INITIALIZING;
}
f.performDetach();
if (!keepActive) {
if (!f.mRetaining) {
makeInactive(f);
} else {
f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
}
}
}
}
}
}
if (f.mState != newState) {
Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
+ "expected state " + newState + " found " + f.mState);
f.mState = newState;
}
}
这一段代码解读
1、正常情况下,fragment的状态f.mState(resume等状态)>newState(INITIALIZING,CREATED)的,走到第二个if分支,fragment的状态有如下几个,分别对应不同的生命周期
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.
2、注意这里的switch case没有break,所以依次调用case Fragment.RESUMED,case Fragment.STARTED等分支,进去之后肯定满足if (newState < 当前分支的条件状态)条件,所以remove一个fragment , fragment生命周期依次走onPause,onStop等。
3 、到case Fragment.ACTIVITY_CREATED这个分支条件时候,我们看到调用了
f.performDestroyView()方法,也就是remove 一个fragment必走onDestroyView方法。
4、到case Fragment.CREATED分支条件时候,重点来了,由于fragment加入栈,newState为CREATED状态,否则为INITIALIZING 状态,所以我们以不加入栈来分析,newState为INITIALIZING ,满足 if (newState < Fragment.CREATED) 条件,代码走到f.performDestroy()。fragment的生命周期调用到onDestroy方法。
5、我觉得源码写的还是蛮巧妙的,switch case 不写break,状态依次去逐一比对大小,执行生命周期。