Fragment相关源码解析二——生命周期
来源:互联网 发布:js 寄生组合式继承 编辑:程序博客网 时间:2024/06/04 01:11
上次说到BackStackRecord的一系列操作其实是在内部形成了一个Op双向链表,commit() 方法调用后被加入到了FragmentManagerImpl的List中,随后会调用BackStackRecord的run()方法。在看这个方法之前我们首先要明确几件事情。
Fragment的mState
它代表了Fragment的状态,可能被赋值为如下几个值,被初始化的时候默认是INITIALIZING的。
//Fragment.java 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. int mState = INITIALIZING;
FragmentManagerImpl的mCurState
FragmentManagerImpl内部也维护了一个状态来表示Fragment的状态,它在FragmentActivity的生命周期回调时被赋值为相应的状态。
//FragmentManagerImpl.javaint mCurState = Fragment.INITIALIZING;
FragmentActivity的生命周期回调会对Fragment产生影响
FragmentActivity的一系列生命周期回调都会在内部调用mFragments的相应方法。
//FragmentActivity.java protected void onCreate(@Nullable Bundle savedInstanceState) { ..... mFragments.dispatchCreate(); } protected void onStart() { ..... mFragments.dispatchStart(); ..... }
我们知道最终会调用到FragmentManagerImpl的相应方法。最后会调用moveToState 并传入不同的Fragment状态,这里对所有其管辖的Fragment进行了状态转移。那么也就是说Fragment的状态改变可能源自两种情况:1.FragmentActivity的生命周期回调。2.BackStackRecord事务的提交。
//FragmentManagerImpl.java public void dispatchCreate() { mStateSaved = false; moveToState(Fragment.CREATED, false); } public void dispatchActivityCreated() { mStateSaved = false; moveToState(Fragment.ACTIVITY_CREATED, false); } public void dispatchStart() { mStateSaved = false; moveToState(Fragment.STARTED, false); } public void dispatchResume() { mStateSaved = false; moveToState(Fragment.RESUMED, false); } public void dispatchPause() { moveToState(Fragment.STARTED, false); }
BackStackRecord的run()
从整体上来看做了如下几件事情:(1)如果该事务添加到了回退栈,为其Op链中每个Fragment的被回退栈事务引用数加1。(2)遍历该事务的Op链,根据每个Op节点的op.cmd调用FragmentManagerImpl相应的方法。(3)检查完Op链后,要将所有Fragment的状态统一成当前FragmentManagerImpl维护的状态。(4)如果事务最后调用了addToBackStack(),则将该事务添加到回退栈的列表,并调用相应回调函数。
//BackStackRecord.java public void run() { ..... //如果该事务添加到了回退栈,为其Op链中每个Fragment的相应值加1,表示Fragment被回退栈中的事务引用的次数 bumpBackStackNesting(1); ... //遍历Op链,根据op.cmd执行相应的操作 Op op = mHead; while (op != null) { int enterAnim = state != null ? 0 : op.enterAnim; int exitAnim = state != null ? 0 : op.exitAnim; switch (op.cmd) { case OP_ADD: { Fragment f = op.fragment; f.mNextAnim = enterAnim; mManager.addFragment(f, false); } break; ... case OP_HIDE: { Fragment f = op.fragment; f.mNextAnim = exitAnim; mManager.hideFragment(f, transition, transitionStyle); } break; .... case OP_ATTACH: { Fragment f = op.fragment; f.mNextAnim = enterAnim; mManager.attachFragment(f, transition, transitionStyle); } break; ... } op = op.next; } //检查完Op链后,要将所有Fragment的状态统一成当前FragmentManagerImpl维护的状态 mManager.moveToState(mManager.mCurState, transition, transitionStyle, true); //如果调用了addToBackStack() if (mAddToBackStack) { mManager.addBackStackState(this); } }
我们看一下FragmentManagerImpl的一系列xxxFragment()方法中典型的几个,以窥这些方法的大致逻辑。
对于addFragment() ,makeActive(fragment)首先给Fragment分配了mIndex,这是代表已经提交的事务中该Fragment在FragmentManagerImpl(mActive)中的唯一index。在mAdded中添加了该Fragment。为Fragment的mAdded和mRemoving赋值。
//FragmentManagerImpl.java public void addFragment(Fragment fragment, boolean moveToStateNow) { if (mAdded == null) { mAdded = new ArrayList<Fragment>(); } if (DEBUG) Log.v(TAG, "add: " + fragment); //为Fragment分配index makeActive(fragment); if (!fragment.mDetached) { if (mAdded.contains(fragment)) { throw new IllegalStateException("Fragment already added: " + fragment); } mAdded.add(fragment); fragment.mAdded = true; fragment.mRemoving = false; if (fragment.mHasMenu && fragment.mMenuVisible) { mNeedMenuInvalidate = true; } if (moveToStateNow) { moveToState(fragment); } } }
对于removeFragment() ,见注释。
//FragmentManagerImpl.java public void removeFragment(Fragment fragment, int transition, int transitionStyle) { if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting); //是否被回退栈中的事务引用(也就是是否调用了addToBackStack()),没被引用返回true。 final boolean inactive = !fragment.isInBackStack(); //如果不是detached状态或被引用了 if (!fragment.mDetached || inactive) { //mAdded列表中移除该 if (mAdded != null) { mAdded.remove(fragment); } if (fragment.mHasMenu && fragment.mMenuVisible) { mNeedMenuInvalidate = true; } fragment.mAdded = false; fragment.mRemoving = true; //如果没在回退栈中被引用,传入INITIALIZING;如果被引用了,传入CREATED。 //对于moveToState,传入不同的参数会影响Fragment生命周期的回调 //这里关系到Fragment是否会回调onDestroy和onDetach方法,后面再细说。 moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED, transition, transitionStyle, false); } }
看到这里我们知道知道FragmentManagerImpl的xxxFragment()方法都是根据当前Fragment的状态进行一系列在FragmentManagerImpl列表中的添加和删除以及Fragment本身状态的设置等,最后还可能调用FragmentManagerImpl的moveToState() 。
无论在遍历Op链的阶段是否会调用moveToState() (5参,进行单个Fragment的生命周期同步),BackStackRecord的run()都会调用moveToState() (4参,间接调用5参,对所有Fragment进行生命周期同步)。这个方法是FragmentManagerImpl对Fragment进行生命周期管理的重要方法。接下来我们重点看一下这个方法。
FragmentManagerImpl的5参moveToState()
// FragmentManagerImplvoid moveToState(Fragment f)void moveToState(int newState, boolean always)void moveToState(int newState, int transit, int transitStyle, boolean always)void moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive)
有四种重载,最终都会和5参的函数相关,我们来看一下。
这个方法很长,先从整体上对它进行一个了解。
除去开头的一些判断,整体上分为两种情况:Fragment的状态小于newState和Fragment的状态大于newState。switch是没有break的,而在其中的Fragment的生命周期回调会给Fragment的赋新的状态值,也就是说Fragment的会一直回调相应的生命周期方法直到其mState达到了newState。
//FragmentManagerImpl # moveToState()if (f.mState < newState) { switch (f.mState) { case Fragment.INITIALIZING: .... f.onAttach(mHost.getContext()); case Fragment.CREATED: if (newState > Fragment.CREATED) { ... }} else if (f.mState > newState) { ...}
如果newState大于Fragment状态,Fragment会不断进行状态升级,如果newState小于Fragment状态,Fragment会不断进行状态下降。进入每一个case来观察,以一个Fragment从创建到可见,再从可见到销毁为例,大致的流程如下(假设是动态添加Fragment,没被添加到回退栈也没有调用setRetainInstance ):
一个Fragment从创建到RESUMED,它的状态变化和在相应状态的回调函数如下:
INITIALIZING(onAttach、onCreate) -> CREATED(onCreateView、onActivityCreated) -> ACTIVITY_CREATED(onStart ) -> STARTED(onResume ) -> RESUMED
而一个Fragment从RESUMED到被销毁,它的状态变化和在相应状态的回调函数如下:
RESUMED(onPause) -> STARTED(onStop) -> STOPPED(状态赋值为ACTIVITY_CREATED) -> ACTIVITY_CREATED(onDestroyView) -> CREATED(onDestroy、onDetach) -> INITIALIZING
形成一张表如下(注意这里依然没有考虑静态加载、添加到回退栈、setRetainInstance等情况):
借用网上的一个生命周期转移图,如果你理解了moveToState 中Fragment的状态转移和生命周期回调,那么这张图会更加加深你的理解。
下面贴出moveToState 的完整源码,在关键的地方都给出了注释,当然,由于本人水平非常有限,对于Animation还有LoaderManager这样的地方还无法做到完全理解,只能把自己已经理解的东西写上去,大家各取所需。
//FragmentManagerImpl.javavoid moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) { // Fragments that are not currently added will sit in the onCreate() state. // 如果当前Fragment的状态并不是ADD状态,或者已经detach, // 此时设置的newState比如start等会统一修改为CREATED状态,让Fragment仍停留在create状态 if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) { newState = Fragment.CREATED; } // 当一个fragment正在被remove,该fragment应该保持原来的状态 if (f.mRemoving && newState > f.mState) { // While removing a fragment, we can't change it to a higher state. newState = f.mState; } //可以理解为延迟开始的标识,如果当前Fragment的状态还没有走到Fragment.STARTED,那么当mDeferStart为true时,Fragment的状态最多只能到Fragment.STOPPED,无法通过moveToState继续切换到Fragment.STARTED // 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; } //升级状态,让Fragment状态同步到newState if (f.mState < newState) { //因为静态创建和动态创建的时机不一样,我们不想在重新恢复时,Fragment的视图优先于Activity创建(onCreate中会恢复Fragment,而静态的Fragment会在INITIALIZING就恢复View,此时还没执行到Activity的setContentView,mInLayout默认为true,但在状态保存时被置为false) // For fragments that are created from a layout, when restoring from // state we don't want to allow them to be created until they are // being reloaded from the layout. if (f.mFromLayout && !f.mInLayout) { return; } //在切换为最新状态前,动画会被直接忽视掉并直接先把状态切换到动画结束时应该切换到的状态,以走完上次未走完的流程 if (f.mAnimatingAway != null) { // The fragment is currently being animated... but! Now we // want to move our state back up. Give up on waiting for the // animation, move to whatever the final state should be once // the animation is done, and then we can proceed from there. f.mAnimatingAway = null; moveToState(f, f.mStateAfterAnimating, 0, 0, true); } switch (f.mState) { case Fragment.INITIALIZING: if (DEBUG) Log.v(TAG, "moveto CREATED: " + f); //如果是销毁重建,用mSavedFragmentState为Fragment恢复了包括mSavedViewState 、mTarget 、mTargetRequestCode 、mUserVisibleHint的状态。mSavedFragmentState是FragmentState中的一个Bundle,用来持久化一些除了基本状态外的额外数据 if (f.mSavedFragmentState != null) { f.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader()); f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray( FragmentManagerImpl.VIEW_STATE_TAG); f.mTarget = getFragment(f.mSavedFragmentState, FragmentManagerImpl.TARGET_STATE_TAG); if (f.mTarget != null) { f.mTargetRequestCode = f.mSavedFragmentState.getInt( FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0); } f.mUserVisibleHint = f.mSavedFragmentState.getBoolean( FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true); if (!f.mUserVisibleHint) { f.mDeferStart = true; if (newState > Fragment.STOPPED) { newState = Fragment.STOPPED; } } } //为设置一些参数 f.mHost = mHost; f.mParentFragment = mParent; f.mFragmentManager = mParent != null ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl(); f.mCalled = false; //回调生命周期方法onAttach() f.onAttach(mHost.getContext()); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()"); } if (f.mParentFragment == null) { mHost.onAttachFragment(f); } //如果mRetaining字段不为true,也就是没有调用setRetainInstance方法,需回调生命周期方法onCreate(),并将状态状态设置为CREATED if (!f.mRetaining) { f.performCreate(f.mSavedFragmentState); } f.mRetaining = false; //如果是静态加载,我们需要立即初始化View if (f.mFromLayout) { //回调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); //回调onViewCreated() f.onViewCreated(f.mView, f.mSavedFragmentState); } else { f.mInnerView = null; } } 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) { //获取Fragment的container container = (ViewGroup)mContainer.onFindViewById(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; //回调onCreateView(),创建Fragment的视图 f.mView = f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState), container, f.mSavedFragmentState); if (f.mView != null) { f.mInnerView = f.mView; if (Build.VERSION.SDK_INT >= 11) { //对传入的View参数,关闭其层级开始及其以下所有的子View的保存状态不再受其parent的控制; ViewCompat.setSaveFromParentEnabled(f.mView, false); } else { f.mView = NoSaveStateFrameLayout.wrap(f.mView); } if (container != null) { Animation anim = loadAnimation(f, transit, true, transitionStyle); if (anim != null) { setHWLayerAnimListenerIfAlpha(f.mView, anim); f.mView.startAnimation(anim); } //将f.mView添加到container中 container.addView(f.mView); } //如果隐藏,则不显示Fragment if (f.mHidden) f.mView.setVisibility(View.GONE); //回调onViewCreated() f.onViewCreated(f.mView, f.mSavedFragmentState); } else { f.mInnerView = null; } } //回调onActivityCreated(),并将状态设置为ACTIVITY_CREATED f.performActivityCreated(f.mSavedFragmentState); //在这里利用持久化的mSavedFragmentState恢复了View树的状态 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); //回调onStart(),并将状态设置为STARTED f.performStart(); } case Fragment.STARTED: if (newState > Fragment.STARTED) { if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f); //回调onResume(),并将状态设置为RESUMED 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); //回调onPause(),并将状态设置为STARTED f.performPause(); } case Fragment.STARTED: if (newState < Fragment.STARTED) { if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f); //回调onStop(),并将状态设置为STOPPED f.performStop(); } case Fragment.STOPPED: if (newState < Fragment.STOPPED) { if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f); //将状态设置为ACTIVITY_CREATED,并调用了mLoaderManager的一些方法 f.performReallyStop(); } case Fragment.ACTIVITY_CREATED: if (newState < Fragment.ACTIVITY_CREATED) { if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f); if (f.mView != null) { //如果当前状态是ACTIVITY_CREATED且还需要降级,此时如果需要保存View的状态(有几种情况,具体看下一篇),那么保存View树状态。 if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) { saveFragmentViewState(f); } } //回调onDestroyView(),并将状态设置为CREATED f.performDestroyView(); if (f.mView != null && f.mContainer != null) { Animation anim = null; if (mCurState > Fragment.INITIALIZING && !mDestroyed) { // loadAnimation根据fragment.mNextAnim,transit和transitionStyle三个条件返回一个anim anim = loadAnimation(f, transit, false, transitionStyle); } if (anim != null) { final Fragment fragment = f; // anim不为null表示指定了动画,所以mAnimatingAway被赋值为了Fragment的布局文件 f.mAnimatingAway = f.mView; // 并将Fragment需要move to的新状态保存在mStateAfterAnimating中 f.mStateAfterAnimating = newState; final View viewToAnimate = f.mView; // 对动画设置监听 anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener( viewToAnimate, anim) { @Override public void onAnimationEnd(Animation animation) { super.onAnimationEnd(animation); // 当动画结束,才开始继续进行下一步的状态更新操作,并清空mAnimatingAway // 移动的新状态就是动画开始前临时保存在mStateAfterAnimating的状态 if (fragment.mAnimatingAway != null) { fragment.mAnimatingAway = null; moveToState(fragment, fragment.mStateAfterAnimating, 0, 0, false); } } }); // 然后对整个布局文件开始动画 f.mView.startAnimation(anim); } // 不论是否有动画,Fragment所属视图在performDestroyView()后就立即被移除了 f.mContainer.removeView(f.mView); } //将View相关变量置空,交给系统回收 f.mContainer = null; f.mView = null; f.mInnerView = null; } case Fragment.CREATED: if (newState < Fragment.CREATED) { if (mDestroyed) { // 如果动画期间宿主Activity需要destroy了,那么就不应该还要等到Fragment的动画完成的才结束 // 而是直接cancel掉(不会回调onAnimationEnd),并清除mAnimatingAway标识以正常状态流程切换。 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(); } } // 表示正在执行退出动画,只需等待, // 同时更新f.mStateAfterAnimating为最新状态以让动画结束时Fragment能同步至最新状态 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 {// 否则根据正常流程条件依次执行destroy、dettach if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f); //如果并不需要保存实例 if (!f.mRetaining) { //回调onDestroy(),并将状态设置为INITIALIZING f.performDestroy(); } else { f.mState = Fragment.INITIALIZING; } f.mCalled = false; //回调onDetach() f.onDetach(); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onDetach()"); } if (!keepActive) { if (!f.mRetaining) { //释放index,并把该Fragment的一些基本变量初始化为默认值 makeInactive(f); } else { f.mHost = null; f.mParentFragment = null; f.mFragmentManager = null; f.mChildFragmentManager = 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; } }
一些细节
addToBackStack()的影响
当我们调用了BackSatckRecord#addToBackStack() ,只是把mAddToBackStack赋值为true。
//BackSatckRecord.java public FragmentTransaction addToBackStack(String name) { if (!mAllowAddToBackStack) { throw new IllegalStateException( "This FragmentTransaction is not allowed to be added to the back stack."); } mAddToBackStack = true; mName = name; return this; }
commit() 之后,最后在run() 中会受到影响,如果mAddToBackStack为true,那么bumpBackStackNesting(1)会将事务中涉及到的Fragment的mBackStackNesting加1(这个值将会影响Fragment#isInBackStack() 的返回值),接着将这个事务添加到了回退栈中。
//BackSatckRecord.java public void run() { ... bumpBackStackNesting(1); ... if (mAddToBackStack) { mManager.addBackStackState(this); } }
我们关注一下FragmentManagerImpl#removeFragment() ,如果事务被添加到了回退栈,且事务中Fragment被移除,这个Fragment的状态最终会更新到CREATED,只会执行到onDestroyView,不会执行onDestroy和onDetach。
//FragmentManagerImpl.java public void removeFragment(Fragment fragment, int transition, int transitionStyle) { ... final boolean inactive = !fragment.isInBackStack(); if (!fragment.mDetached || inactive) { .... moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED, transition, transitionStyle, false); } }
紧接着按了返回键。
//FragmentActivity.java public void onBackPressed() { if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) { onBackPressedNotHandled(); } }
最终调用到下面这个方法,看一下第一个if里面,从回退栈中出栈了一个事务,并调用了popFromBackStack 。
//FragmentManagerImpl.java@SuppressWarnings("unused") 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; } final BackStackRecord bss = mBackStack.remove(last); SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); bss.calculateBackFragments(firstOutFragments, lastInFragments); bss.popFromBackStack(true, null, firstOutFragments, lastInFragments); reportBackStackChanged(); } else { ... } return true; }
看一下这个方法,依据op.cmd执行相反的操作,我们的假设的是Fragment被remove后添加进回退栈,那么此时它的状态是CREATED,接着需要进行升级同步(按了回退键,立即同步到Activity的状态,见下面源码),那么它不会执行onAttach和onCreate回调,会直接执行onCreateView和onActivityCreated等回调 。
//BackSatckRecord.java public TransitionState popFromBackStack(boolean doStateMove, TransitionState state, SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) { ... bumpBackStackNesting(-1); .... Op op = mTail; while (op != null) { int popEnterAnim = state != null ? 0 : op.popEnterAnim; int popExitAnim= state != null ? 0 : op.popExitAnim; switch (op.cmd) { ... case OP_REMOVE: { Fragment f = op.fragment; f.mNextAnim = popEnterAnim; mManager.addFragment(f, false); } break; ... default: { throw new IllegalArgumentException("Unknown cmd: " + op.cmd); } } op = op.prev; } //传入的是true,立刻同步所有Fragment的状态到Activity的状态 if (doStateMove) { mManager.moveToState(mManager.mCurState, FragmentManagerImpl.reverseTransit(transition), transitionStyle, true); state = null; } ... return state; }
setRetainInstance(true)的影响
这个方法也是简单地为一个变量赋值。
//Fragment.java public void setRetainInstance(boolean retain) { if (retain && mParentFragment != null) { throw new IllegalStateException( "Can't retain fragements that are nested in other fragments"); } mRetainInstance = retain; }
在FragmentActivity因为配置变化而需要保存Fragment的状态的时候。
//FragmentActivity.java public final Object onRetainNonConfigurationInstance() { ... List<Fragment> fragments = mFragments.retainNonConfig(); ... }
最终调用的是FragmentManagerImpl的方法,可以看到,如果Fragment的mRetainInstance为true,则其mRetaining被置为true并被添加到一个List中(稍后返回给系统)。
//FragmentManagerImpl.java ArrayList<Fragment> retainNonConfig() { ArrayList<Fragment> fragments = null; if (mActive != null) { for (int i=0; i<mActive.size(); i++) { Fragment f = mActive.get(i); if (f != null && f.mRetainInstance) { if (fragments == null) { fragments = new ArrayList<Fragment>(); } fragments.add(f); f.mRetaining = true; f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1; if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f); } } } return fragments; }
Fragment的mRetaining被置为true之后会对它的生命周期产生怎样的影响?首先在降级同步中,它不会回调onDestroy方法,也不会使自己的index失效。
//FragmentManagerImpl.java void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) { ... if (!f.mRetaining) { f.performDestroy(); } if (!f.mRetaining) { makeInactive(f); } ... }
然后在恢复Fragment状态的升级同步中,它不会回调onCreate方法。
//FragmentManagerImpl.java void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) { ... if (!f.mRetaining) { f.performCreate(f.mSavedFragmentState); } f.mRetaining = false; ... }
直接添加Fragment带来的问题
如果用户不自己处理配置的变化,在FragmentActivity被重建回调onCreate时,会利用FragmentManagerState的mActive重建Fragment,如果此时用户重写onCreate还添加了该Fragment,就会出现两个Fragment,所以要加入判断。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(v); MyFragment myFragment = (MyFragment) getSupportFragmentManager().findFragmentByTag("MyFragmentTag"); if ( myFragment == null ){ myFragment = new BlankFragment(); getSupportFragmentManager().beginTransaction().add(R.id.container, myFragment, "MyFragmentTag").commit(); }}
- Fragment相关源码解析二——生命周期
- Fragment相关源码解析一——FragmentManagerImpl和BackStackRecord
- 从源码来看Fragment的生命周期(二)
- Fragment相关源码解析三——状态保存与恢复
- Android—Fragment生命周期
- Fragment生命周期相关
- Fragment生命周期及解析
- Fragment生命周期解析
- Android Fragment生命周期解析
- Fragment生命周期完全解析
- fragment生命周期二
- Android Fragment——处理Fragment生命周期
- Fragment学习笔记——Fragment生命周期和Fragment通信
- Fragment实例化,Fragment生命周期源码分析
- Android之fragment生命周期解析
- Fragment详解(二)--->生命周期详解
- Fragment详解(二)--->生命周期详解
- Fragment源码解析
- java的模板方法设计模式
- SQLite/sharePreference可视化工具
- 一分钟了解”Matlab中ClassificationEnsemble集成分类方法的ScoreTransform具体公式”
- poj 2031 Building a Space Station
- 学习笔记——JAVA设计模式<16>解释器模式
- Fragment相关源码解析二——生命周期
- 服务机器人的小脑——SLAM技术
- php-12
- 添加字符
- Oracle 课程设计源码
- 脚本
- 将一个字符串转换成一个整数
- DataGridView很详细的用法
- php 异步websocket客户端实现