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);
}
}
// 第三步:新添加的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相关代码较多,以上也只是一点粗陋的分析,接下来的路还很漫长。

948

被折叠的 条评论
为什么被折叠?



