从源码来看Fragment的生命周期(二)
来源:互联网 发布:java基本命名规范 编辑:程序博客网 时间:2024/06/07 23:08
7、moveToState
上一盘说Fragment的生命周期说到了moveToState这个方法,这篇我们继续:
首先看moveToState这个方法的定义:
void moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive)
static final int INVALID_STATE = -1; // Invalid state used as a null value.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.
在moveToState方法一开始,会对传入的newState进行校准,具体方式如下:
//如果传入的newState大于Fragment.CREATED,那么在两种情况下将他强行设置为Fragment.CREATED//1、这个fragment已经被移除了,即调用removeFragment方法//2、这个fragment已经没有附着在当前activity上了,即调用了detachFragment方法if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) { newState = Fragment.CREATED;}//如果fragment已经被remove掉了,那么如果传入的newState大于原始的mState时,是不能增加mState的值的if (f.mRemoving && newState > f.mState) { // While removing a fragment, we can't change it to a higher state. newState = f.mState;}//如果fragment要求延时start,并且fragment的原状态小于STARTED,而传入的状态大于STOPPED(最少为STARTED),那么强行将状态置为STOPPEDif (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) { newState = Fragment.STOPPED;}
校准完毕之后,就开始同步状态,同步状态有两种情况,一种是传入的newState大于原有的mState,这时状态会上升,另外一种是小于,这时状态会下降。
在状态上升中,是通过switch-case进行不同分支跳转的,但是在这个case的最后并没有使用break语句跳出分支,这时因为在执行完前一个状态的逻辑后,还需要继续往后执行,所有它其中的case分支都是按照INITIALIZING、CREATED、ACTIVITY_CREATED、STOPPED、STARTED、RESUMED顺序排布的,因为代码较长,所以这里都以注释的形式进行说明。
INITIALIZING:
//首先会判断mSavedFragmentState是否为null,这个是用来保存状态恢复而使用的,和Activity非正常销毁时保存状态类似if (f.mSavedFragmentState != null) { ......}//配置fragment的参数......//验证一些信息f.mCalled = false;f.onAttach(mActivity);if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()");}if (f.mParentFragment == null) { mActivity.onAttachFragment(f);}//执行fragment的生命周期if (!f.mRetaining) { //在这里会调用fragment的performCreate方法,在performCreate方法中会调用生命周期的onCreate方法 f.performCreate(f.mSavedFragmentState);}f.mRetaining = false;//如果这个fragment是layout中的,那么还执行另外的一些生命周期if (f.mFromLayout) { //performCreateView方法中会调用onCreateView方法 f.mView = f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState), null, f.mSavedFragmentState); //如果从onCreateView获得的View不为null,那么还会调用onViewCreated方法 if (f.mView != null) { f.mView.setSaveFromParentEnabled(false); if (f.mHidden) f.mView.setVisibility(View.GONE); f.onViewCreated(f.mView, f.mSavedFragmentState); }}
CREATED:
//因为上面的一个case没有break,所以从第二个case开始,都会先判断newState,才能决定是否继续执行当前state的逻辑if (newState > Fragment.CREATED) { if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f); //如果fragment不是layout中的,那么就会执行fragment的生命周期(和INITIALIZING中类似) //不过这里还添加了一个新的逻辑,那就是拿到fragment需要填充的view的id,在fragment的view构建完毕之后, //通过container.addView(f.mView),将fragment添加到需要填充的view中, if (!f.mFromLayout) { ViewGroup container = null; if (f.mContainerId != 0) { 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; f.mView = f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState), container, f.mSavedFragmentState); if (f.mView != null) { f.mView.setSaveFromParentEnabled(false); if (container != null) { Animator anim = loadAnimator(f, transit, true, transitionStyle); if (anim != null) { anim.setTarget(f.mView); setHWLayerAnimListenerIfAlpha(f.mView, anim); anim.start(); } container.addView(f.mView); } if (f.mHidden) f.mView.setVisibility(View.GONE); f.onViewCreated(f.mView, f.mSavedFragmentState); } } //执行完生命周期之后,调用ChildFragment中的performActivityCreated方法,这样最终会调用到ChildFragment中的moveToState方法 f.performActivityCreated(f.mSavedFragmentState); if (f.mView != null) { f.restoreViewState(f.mSavedFragmentState); } f.mSavedFragmentState = null;}
ACTIVITY_CREATED:
STOPPED:
if (newState > Fragment.STOPPED) { if (DEBUG) Log.v(TAG, "moveto STARTED: " + f); //如果newState大于STOPPED(至少是STARTED),那么调用fragment的生命周期onStart方法 f.performStart();}
STARTED:
if (newState > Fragment.STARTED) { if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f); f.mResumed = true; //调用fragment的生命周期onResume f.performResume(); f.mSavedFragmentState = null; f.mSavedViewState = null;}
到这里,提升状态的逻辑基本就说完了,理解完提升状态的逻辑,那么降低状态的逻辑也就大同小异了,这里就放一起说了:
降低状态:
case Fragment.RESUMED:if (newState < Fragment.RESUMED) { if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f); //如果小于RESUMED,那么调用生命周期onPause f.performPause(); f.mResumed = false;}case Fragment.STARTED:if (newState < Fragment.STARTED) { if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f); //如果小于STARTED,那么调用生命周期onStop f.performStop();}case Fragment.STOPPED:case Fragment.ACTIVITY_CREATED:if (newState < Fragment.ACTIVITY_CREATED) { if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f); //如果mView不为null,清除之前保存的一些状态 if (f.mView != null) { if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) { saveFragmentViewState(f); } } //调用onDestroyView生命周期方法 f.performDestroyView(); //如果有退出动画,那么播放退出动画 if (f.mView != null && f.mContainer != null) { Animator anim = null; if (mCurState > Fragment.INITIALIZING && !mDestroyed) { anim = loadAnimator(f, transit, false, transitionStyle); } if (anim != null) { final ViewGroup container = f.mContainer; final View view = f.mView; final Fragment fragment = f; container.startViewTransition(view); f.mAnimatingAway = anim; f.mStateAfterAnimating = newState; anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator anim) { container.endViewTransition(view); if (fragment.mAnimatingAway != null) { fragment.mAnimatingAway = null; moveToState(fragment, fragment.mStateAfterAnimating, 0, 0, false); } } }); anim.setTarget(f.mView); setHWLayerAnimListenerIfAlpha(f.mView, anim); anim.start(); } //将fragment的view从界面移除 f.mContainer.removeView(f.mView); } f.mContainer = null; f.mView = null;}case Fragment.CREATED:if (newState < Fragment.CREATED) { if (mDestroyed) { //如果fragment的Activity销毁,那么停止fragment的动画,并将mAnimatingAway设置为null if (f.mAnimatingAway != null) { Animator anim = f.mAnimatingAway; f.mAnimatingAway = null; anim.cancel(); } } if (f.mAnimatingAway != null) { //如果mAnimatingAway没有设置为null,那么状态不变 f.mStateAfterAnimating = newState; newState = Fragment.CREATED; } else { //如果mAnimatingAway状态为null if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f); if (!f.mRetaining) { //调用fragment的生命周期onDestroy f.performDestroy(); } f.mCalled = false; //调用fragment的生命周期onDetach f.onDetach(); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onDetach()"); } if (!keepActive) { if (!f.mRetaining) { //回收fragment的index makeInactive(f); } else { f.mHost = null; f.mParentFragment = null; f.mFragmentManager = null; f.mChildFragmentManager = null; } } }}
总结
①到这里,Fragment的源码也算是基本完结了,相比于Activity,Fragment更像一个java类,它没有Activity那样实现很多的视图接口,也没有实现任何的键盘监听,从这里我们就可以确定fragment里的键盘事件应该是通过Activity传入的。
②在我们使用Fragment的时候,通过getFragmentManager方法拿到的其实是FragmentManagerImpl,他是FragmentManagerI的子类。而Fragment的生命周期,也是通过它进行控制的。
③在我们通过beginTransaction,add方法添加Fragment的时候,只是把Fragment和操作类型保存到一个BackStackRecord的Op对象中去了,虽然Fragment对象是通过我们new Fragment创建出来的,但是此时的Fragment并没有执行它生命周期的onCreate方法,这点和Activity是不同的,Activity是会在系统创建它之后,立刻执行它出onCreate方法。
④对Fragment状态的的变更,是在我们调用完commit方法后才开始的,他会通过mHandler.post(mExecCommit),最后调用到execPendingActions方法中。
⑤在execPendingActions方法中,会拿到之前在BackStackRecord对象,而BackStackRecord是实现了Runnable接口是,所以会执行BackStackRecord中的run方法。
⑥在BackStackRecord 的run中,会针对不同的操作类型,比如add,remove调用FragmentManagerImpl中不同的方法,例如addFragment,removeFragment,在这些方法中,首先会更改fragment对象中对应的配置参数,然后会将fragment传入调用moveToState方法。
⑦在FragmentManagerImpl的moveToState方法中,会调用Fragment的生命周期方法。
上述,就是Fragment源码中,对于Fragment生命周期的调用了,当然还是那句话,Android的源码远比我看的复杂,而我当前也只是通过一个简单的例子来看Fragment的生命周期,自然不可能面面俱到,至于其中的细节部分,还是需要以后慢慢研究咯。
- 从源码来看Fragment的生命周期(二)
- 从源码来看Fragment的生命周期(一)
- 从源码来看auto_ptr的特性
- 源码剖析Fragment的Pause生命周期
- 从官方api理解fragment,以及fragment的生命周期
- 详解fragment(一):从源代码看fragment的生命周期
- Fragment相关源码解析二——生命周期
- 解决fastjson无序的问题--从源码的角度来看
- fragment生命周期二
- 从 FingBugs的错误来看JAVA代码质量(二)
- 从 FingBugs的错误来看JAVA代码质量(二)
- 从一个最简单的例子来看Retrofit(二)
- 从activity回到fragment生命周期
- 从FragmentPagerAdapter看Fragment 生命周期
- Fragment实例化,Fragment生命周期源码分析
- 从commit一步步带你走向fragment的生命周期
- Fragment详解(二)--->生命周期详解
- Fragment详解(二)--->生命周期详解
- MySQL5.7安装教程及常见问题解决
- 12112
- 结构体与指针
- webservice_axis1_Rmi_Remote_接口调用
- CScrollView Scroll初始化
- 从源码来看Fragment的生命周期(二)
- 20161211计算机科学导论07_软件与硬件
- Ubuntu 学习路径-1-体验gnome并连接网络
- BroadcastReceiver使用完全解析
- ASPxGridview自定义分页
- iOS取消应用订阅
- Codeforces Round #381 (Div. 1) C
- java 集合框架
- 几个常用绑定数据的方法