上次说到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.java
int 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()
// FragmentManagerImpl
void moveToState(Fragment f)
void moveToState(int newState, boolean