Fragment FragmentManager FragmentTransaction源码浅析
2018-03-02 16:26
225 查看
Fragment相关类的关系及说明
UML类图
上图虽然不是
Fragment工作过程中所有类,但是也能表达
Fragment工作过程中主要类的关系。下面对一些类进行简要的说明。
相关类说明
HostCallbacks:
FragmentActivity内部类,继承
FragmentHostCallback,在其相应方法中调用
FragmentActivity的相应方法,实现其功能。实例化
FragmentController时传入。
FragmentController:
FragmentActivity主要是通过它来对
Fragment进行相应的操作。
FragmentController利用
FragmentActivity实现的
FragmentHostCallback获取
FragmentManagerImpl,提供
Fragment生命周期分发方法。
FragmentHostCallback<E>:提供
Fragment一些回调方法实现,持有宿主
Activity的引用,持有
FragmentManagerImpl实例。
FragmentManagerImpl:
FragmentManager具体实现,并且实现了
LayoutInflater.Factory接口。管理宿主中的所有
Fragment。
BackStackRecord:继承
FragmentTransaction,提供事务操作及事务相关操作的记录,在进行返回栈操作时便于事务的恢复。
Op:
BackStackRecord内部类,用于存储
Fragment操作类型及进出动画。
Fragment生命周期
想要了解Fragment生命周期,当然是进入
FragmentActivity了,因为
Fragment生命周期和
Activity生命周期息息相关嘛。
进入
FragmentActivity直接搜索
Fragment,首先我们可以找到一个叫
mFragments的常量:
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
再接着搜索,可以在
FragmentActivity相关生命周期方法中找到
mFragments的使用:
protected void onCreate(@Nullable Bundle savedInstanceState) { ... mFragments.dispatchCreate(); } ...// 这里只展示一个,其他生命周期方法类同
至此,我们可以知道
Fragment的生命周期为什么和
Activity生命周期息息相关了。接着我们再看看
mFragments也就是
FragmentController中相关方法:
private final FragmentHostCallback<?> mHost; public static final FragmentController createController(FragmentHostCallback<?> callbacks) { return new FragmentController(callbacks); } private FragmentController(FragmentHostCallback<?> callbacks) { mHost = callbacks; } public void dispatchStart() { mHost.mFragmentManager.dispatchStart(); }
FragmentController相关方法其内部调用的
FragmentManager的方法,跟踪代码发现,首先会进入
moveToState(int newState, boolean always)方法中,在其中会遍历所以已添加和处于活动中的
Fragment进行下一步处理:
void moveToState(int newState, boolean always) { ... if (mActive != null) { boolean loadersRunning = false; // Must add them in the proper order. mActive fragments may be out of order final int numAdded = mAdded.size(); for (int i = 0; i < numAdded; i++) { Fragment f = mAdded.get(i); moveFragmentToExpectedState(f); if (f.mLoaderManager != null) { loadersRunning |= f.mLoaderManager.hasRunningLoaders(); } } // Now iterate through all active fragments. These will include those that are removed // and detached. final int numActive = mActive.size(); for (int i = 0; i < numActive; i++) { Fragment f = mActive.valueAt(i); if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) { moveFragmentToExpectedState(f); if (f.mLoaderManager != null) { loadersRunning |= f.mLoaderManager.hasRunningLoaders(); } } } if (!loadersRunning) { startPendingDeferredFragments(); } if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) { mHost.onSupportInvalidateOptionsMenu(); mNeedMenuInvalidate = false; } } }
然后进入
moveFragmentToExpectedState()方法中,首先会进入
moveToState(Fragment,newState,transit,transitionStyle,keepActive)方法中进行状态分发,根据不同的状态进行处理相应的逻辑,例如在
Create状态将
View添加到
Activity的
ViewGroup中等;然后进行
View的移动,确保
Fragment的
View以正确的顺序显示;最后执行动画:
void moveFragmentToExpectedState(Fragment f) { if (f == null) { return; } int nextState = mCurState; if (f.mRemoving) { if (f.isInBackStack()) { nextState = Math.min(nextState, Fragment.CREATED); } else { nextState = Math.min(nextState, Fragment.INITIALIZING); } } // 第一步:根据不同状态进行分发 moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false); if (f.mView != null) { // 第二步:移动View在Activity的ViewGroup中的显示顺序 // Move the view if it is out of order Fragment underFragment = findFragmentUnder(f); if (underFragment != null) { final View underView = underFragment.mView; // make sure this fragment is in the right order. final ViewGroup container = f.mContainer; int underIndex = container.indexOfChild(underView); int viewIndex = container.indexOfChild(f.mView); if (viewIndex < underIndex) { container.removeViewAt(viewIndex); container.addView(f.mView, underIndex); } d694 } // 第三步:新添加的Fragment,执行动画 if (f.mIsNewlyAdded && f.mContainer != null) { // Make it visible and run the animations if (f.mPostponedAlpha > 0f) { f.mView.setAlpha(f.mPostponedAlpha); } f.mPostponedAlpha = 0f; f.mIsNewlyAdded = false; // run animations: AnimationOrAnimator anim = loadAnimation(f, f.getNextTransition(), true, f.getNextTransitionStyle()); if (anim != null) { setHWLayerAnimListenerIfAlpha(f.mView, anim); if (anim.animation != null) { f.mView.startAnimation(anim.animation); } else { anim.animator.setTarget(f.mView); anim.animator.start(); } } } } // 第四步:判断Fragment显示隐藏是否改变,如改变,则在completeShowHideFragment中执行动画 if (f.mHiddenChanged) { completeShowHideFragment(f); } }
以上是
Activity生命周期触发
Fragment生命周期的过程,至于动态添加
Fragment,实际上最终也是到
moveToState(Fragment,newState,transit,transitionStyle,keepActive)中根据状态进行处理。
Fragment事务
在开发中,我们通常都是使用事务来操作Fragment的添加、显示、隐藏的,那么其内部是如何处理的呢?
首先,我们来看下
add()、
hide()、
show()、
replace()方法中是如何处理的。进入
BackStackRecord类查看代码发现,它们都调用了
doAddOp()方法:
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) { ...// 省略其他内容 addOp(new Op(opcmd, fragment)); }
doAddOp()方法最终会创建一个
Op()对象,并添加到集合中保存。
Op类我们在开始的时候说过,主要是用来存储
Fragment操作类型的,也就是
cmd,它的可选参数有:
static final int OP_NULL = 0; static final int OP_ADD = 1; static final int OP_REPLACE = 2; static final int OP_REMOVE = 3; static final int OP_HIDE = 4; static final int OP_SHOW = 5; static final int OP_DETACH = 6; static final int OP_ATTACH = 7; static final int OP_SET_PRIMARY_NAV = 8; static final int OP_UNSET_PRIMARY_NAV = 9;
通过上面查看代码,我们可以发现:开启事务后我们进行的
add()、
hide()等操作都会以
Op()对象的形式存储在集合中。接下来我们看看最后我们所调用的
commit()又做了些什么?
查看
commit()方法发现其调用的是
commitInternal()方法:
int commitInternal(boolean allowStateLoss) { ...//省略部分代码 mManager.enqueueAction(this, allowStateLoss); return mIndex; }
在其中调用的是
FragmentManager的
enqueueAction()方法,会将当前
BackStackRecord实例传入其中:
public void enqueueAction(OpGenerator action, boolean allowStateLoss) { if (!allowStateLoss) { checkStateLoss(); } synchronized (this) { if (mDestroyed || mHost == null) { if (allowStateLoss) { // This FragmentManager isn't attached, so drop the entire transaction. return; } throw new IllegalStateException("Activity has been destroyed"); } if (mPendingActions == null) { mPendingActions = new ArrayList<>(); } mPendingActions.add(action); scheduleCommit(); } }
在
enqueueAction方法中,将
action排入队列,最后调用
scheduleCommit()方法:
private void scheduleCommit() { synchronized (this) { boolean postponeReady = mPostponedTransactions != null && !mPostponedTransactions.isEmpty(); boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1; if (postponeReady || pendingReady) { mHost.getHandler().removeCallbacks(mExecCommit); mHost.getHandler().post(mExecCommit); } } } Runnable mExecCommit = new Runnable() { @Override public void run() { execPendingActions(); } };
查看代码发现,最后调用的是
FragmentHostCallback的
Handler进行异步操作,此
Handler实际上是
FragmentActivity的。
跟踪代码发现
execPendingActions()方法最后会调用
BackStackRecord的
executePopOps()或
executeOps()方法来处理具体的操作:
void executePopOps(boolean moveToState) { for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) { final Op op = mOps.get(opNum); Fragment f = op.fragment; if (f != null) { f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } //根据Op类型,调用FragmentManager相关方法,改变Fragment状态 switch (op.cmd) { case OP_ADD: f.setNextAnim(op.popExitAnim); mManager.removeFragment(f); break; case OP_REMOVE: f.setNextAnim(op.popEnterAnim); mManager.addFragment(f, false); break; case OP_HIDE: f.setNextAnim(op.popEnterAnim); mManager.showFragment(f); break; case OP_SHOW: f.setNextAnim(op.popExitAnim); mManager.hideFragment(f); break; case OP_DETACH: f.setNextAnim(op.popEnterAnim); mManager.attachFragment(f); break; case OP_ATTACH: f.setNextAnim(op.popExitAnim); mManager.detachFragment(f); break; case OP_SET_PRIMARY_NAV: mManager.setPrimaryNavigationFragment(null); break; case OP_UNSET_PRIMARY_NAV: mManager.setPrimaryNavigationFragment(f); break; default: throw new IllegalArgumentException("Unknown cmd: " + op.cmd); } if (!mReorderingAllowed && op.cmd != OP_REMOVE && f != null) { // 上面讲生命周期的时候有相应描述 mManager.moveFragmentToExpectedState(f); } } if (!mReorderingAllowed && moveToState) { // 上面讲生命周期的时候有相应描述 mManager.moveToState(mManager.mCurState, true); } }
总结
Fragment相关代码较多,以上也只是一点粗陋的分析,接下来的路还很漫长。
相关文章推荐
- js继承 Base类的源码解析
- Java源码解析之GenericDeclaration详解
- Android Fragment 和 FragmentManager 的代码分析
- 重新认识java-LinkedList
- tio-http-server 源码浅析(一)HttpRequestDecoder的实现
- tio-http-server 源码浅析(二)Http请求的处理HttpRequestHandler
- tio-websocket-server 源码浅析
- Mybatis3.4.x技术内幕(十八):Mybatis之动态Sql设计原本(下)
- Mybatis3.4.x技术内幕(十九):Mybatis之plugin插件设计原理
- 多线程(三)之ReentrantLock源码解析
- MyBatis(3.4.2)的Cache机制完全解析
- Spring IoC源码解析(一)——配置文件加载和IoC容器初始化
- ScheduledThreadPoolExecutor详解
- android:fitSystemWindows详解
- android:fitSystemWindows详解
- Spring源码解析:自定义标签的解析过程
- Spring源码解析:Bean实例的创建与初始化
- Spring源码解析:高级容器的扩展内幕
- Spring源码解析:循环依赖的探测与处理
- Spring event 和 Guava event