当使用FragmentManager,对fragment作出操作,执行commit方法时,先会对生成的BackStackRecord进行检查是否有添加,而在enqueue方法中会通过handler机制,发送一个名叫mExecCommit的Runnable对象,将事件发送到添加到主线程中进行执行。
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
...
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
而对于fragment的操作会转化为一个或多个BackStackRecord中的mOps中的Op对象(如replace操作就会生成两个Op对象,每个Op对象会对应到一个FragmentManagerImpl的一个操作,包括addFragment,removeFragment,hideFragment,showFragment,detachFragment,attachFragment)。经过一系列处理后,最终会调用到FragmentManagerImpl的addFragment等方法把view与viewTree产生联系。 而在FragmentManagerImpl的addFragment方法中会检查要加入的Fragment是否已经加入过了。
public void addFragment(Fragment fragment, boolean moveToStateNow) {
makeActive(fragment);
if (!fragment.mDetached) {
if (mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
synchronized (mAdded) {
mAdded.add(fragment);
}
fragment.mAdded = true;
fragment.mRemoving = false;
if (fragment.mView == null) {
fragment.mHiddenChanged = false;
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
moveToState(fragment);
}
}
}
当messageQueue中的mExecCommit执行的时,目标BackStackRecord对象的mReorderingAllowed为true,会对添加了的其他Fragment调整生命周期。
在Activity继承的FragmentActivityh每个生命周期中会有一些调用来调用添加了的Fragment的生命周期。来保持fragment的生命周期和activity的生命周期一致。
//FragmentActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mFragments.attachHost(null /*parent*/);
super.onCreate(savedInstanceState);
...
mFragments.dispatchCreate();
}
这里会调用到FragmentManagerImpl的moveToState方法,挨个的改变fragment的生命周期。
final ArrayList<Fragment> mAdded = new ArrayList<>();
void moveToState(int newState, boolean always) {
...
mCurState = newState;
if (mActive != null) {
// 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);
}
}
}
若在activity的每一次生命周期中调用FragmentManager的诸如replace方法,调用后会向主线程的looper发送一个Runnable,这个runnable执行的时候会对你的目标fragment/所有添加乐的fragment的生命周期进行处理。
例如,在activity的onCreate方法里写入getSupportFragmentManager().beginTransaction().replace(R.id.xxx,fragment).commit()。这时你的fragment还在FragmentManagerd的mAdded之中,当出现activity的生命周期变化时,这个fragment的生命周期也会跟着改变,在activity的销毁中没有问题。而如果activity要重建(例如分屏操作),执行到onCreate写入的方法,会先向主线程的looper中发送一个Runnable对象,并且继续执行生命周期,当looper执行到发送的Runnable后,会先调用FragmentManagerImpl的removeFragment,而后再调用addFregment。而这里的两个调用都会依次fragment的生命周期。
而这里的fragment又是同一个,此时就会出现fragment的生命周期被调用两次的情况,。而如果不触发activity的重建则不会出现这种情况。