您的位置:首页 > 其它

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
相关代码较多,以上也只是一点粗陋的分析,接下来的路还很漫长。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息