标准的Fragment声明周期
入口分析
从FragmentActivity 开始看 onCreate 等很多分发操作,看下整个核心架构图
FragmentActivity上的所有生命周期相关API都会调用
FragmentController对应的dispatchXXX()
mFragments.dispatchCreate();
mHost.mFragmentManager.dispatchCreate();
FragmentManager 是通过FragmentManagerImpl 实现大量的 dispatchXXX 分发操作
核心: activitylifecycle ------> dispatchStateChange
public void dispatchCreate() {
mStateSaved = false;
mStopped = false;
dispatchStateChange(Fragment.CREATED);
}
public void dispatchActivityCreated() {
mStateSaved = false;
mStopped = false;
dispatchStateChange(Fragment.ACTIVITY_CREATED);
}
public void dispatchStart() {
mStateSaved = false;
mStopped = false;
dispatchStateChange(Fragment.STARTED);
}
public void dispatchResume() {
mStateSaved = false;
mStopped = false;
dispatchStateChange(Fragment.RESUMED);
}
public void dispatchPause() {
dispatchStateChange(Fragment.STARTED);
}
public void dispatchStop() {
mStopped = true;
dispatchStateChange(Fragment.ACTIVITY_CREATED);
}
public void dispatchDestroyView() {
dispatchStateChange(Fragment.CREATED);
}
public void dispatchDestroy() {
mDestroyed = true;
execPendingActions();
dispatchStateChange(Fragment.INITIALIZING);
mHost = null;
mContainer = null;
mParent = null;
}
private void dispatchStateChange(int nextState) {
try {
mExecutingActions = true;
moveToState(nextState, false);
} finally {
mExecutingActions = false;
}
execPendingActions();
}
这五个状态控制了声明周期 配合dispatchxxx 方法
生命周期的调用都会走到这个方法中
dispatchStateChange(Fragment.CREATED)
static final int INITIALIZING = 0; // Not yet created.
static final int CREATED = 1; // Created.
static final int ACTIVITY_CREATED = 2; // Fully created, not started.
static final int STARTED = 3; // Created and started, not resumed.
static final int RESUMED = 4; // Created started and resumed.
int mState = INITIALIZING;
通过源代码,发现核心就是这个方法管理状态
void moveToState(int newState, boolean always)
final ArrayList
moveFragmentToExpectedState(f); 加入到mAdded集合
接下来
在这个方法中去回调Fragment生命周期的方法
moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
初始化状态INITIALIZING
所以我们先走到f.onAttach(mHost.getContext());---> dispatchOnFragmentAttached(f, mHost.getContext(), false);
void dispatchOnFragmentCreated(@NonNull Fragment f, @Nullable Bundle savedInstanceState,
boolean onlyRecursive) {
最后回调这里。其他声明周期整个流程类似
void performCreate(Bundle savedInstanceState)
状态赋值 CREATE
Switch 里面的 思路就是
创建声明周都是从CREATE开始向下 流
反过来下面的部分就反向流标记是 RESUMED
我们从用户的使用角度看,来分析,所有的操作有如下这些
// TODO: 2020/9/23 查看测试Fragment androidX 源代码入口
// ft.add()
// ft.remove();
// ft.replace();
// ft.hide();
// ft.show();
// TODO: 2020/9/23 导航相关
// ft.setPrimaryNavigationFragment();
// TODO: 2020/9/23 加入回退栈
// ft.addToBackStack();
// ft.commit()
// ft.commitAllowingStateLoss()
// ft.commitNow();
// ft.commitNowAllowingStateLoss();
// TODO: 2020/9/23 END
FragmentTransaction 事务就是一组操作要么全做,要么全部做
开启事务返回BackStackRecord 每一个这个就是一个事务
add---->addOp
addOp(new Op(opcmd, fragment));
commit-> commitInternal
mManager.enqueueAction(this, allowStateLoss);
存入 ArrayList
void scheduleCommit()::mHost.getHandler().post(mExecCommit);
mExecCommit 任务
/**
* Only call from main thread!
*/
public boolean execPendingActions() {
ensureExecReady(true);
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
doPendingDeferredStart();
burpActive();
return didSomething;
}/**
* Only call from main thread!
*/
public boolean execPendingActions() {
这里的动作就是:循环判断和赋值这两个集合记录generateOpsForPendingActions
ArrayList mTmpRecords;
ArrayList mTmpIsPop;
调用 BackStackRecore-> generateOps 或者 PopStackStateImpl-> generateOps
目的就是给这个 mTmpIsPop 赋值 并且吧pendingAction 集合 操作放到record,因为之前事务执行add栈操作和没有执行的进行分类
接下来会做一个裁剪操作 removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop)
相当与做了优化,重复操作add栈不会执行
BackStackRecord 标记
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;
executeOpsTogether-》expandOps
OP_ADD,OP_ATTACH 都是 add 操作。OP_REMOVE,OP_DETACH 都是remove操作 然后判断导航add
OP_REPLACE 判断是否是同一个id,相同不操作。
这些操作内部优化大部分变成add 操作。
优化结束开始执行操作,执行真正的【提交】
executeOps 一开是isProp false
进入switch,执行上面所有对应标记的操作
addFragment ----》 又执行到了【moveToState(fragment);】就会执行声明周期了
这样就进行合并执行的操作,整个流程,有点像状态机
之前的操作都被分解成OP_ADD
addToBackStack
流程
commitInternal 有个判断如果mAddToBackStack
-> allocBackStackIndex
public int allocBackStackIndex(BackStackRecord bse) {
synchronized (this) {
if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
if (mBackStackIndices == null) {
mBackStackIndices = new ArrayList();
}
int index = mBackStackIndices.size();
if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
mBackStackIndices.add(bse);
return index;
} else {
int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1);
if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
mBackStackIndices.set(index, bse);
return index;
}
}
}
// Must be accessed while locked.
ArrayList mBackStackIndices;
ArrayList mAvailBackStackIndices;
public void freeBackStackIndex(int index) {
synchronized (this) {
mBackStackIndices.set(index, null);
if (mAvailBackStackIndices == null) {
mAvailBackStackIndices = new ArrayList();
}
if (DEBUG) Log.v(TAG, "Freeing back stack index " + index);
mAvailBackStackIndices.add(index);
}
}
操作这两个集合,有一个算法
之前是双端链表不断添加删除,现在改成两个集合算法,没有删除操作,并且空间可复用
大体算法意思,mBackStackIndices 中添加 fragment mAvailBackStackIndices 记录空闲索引值进行复用
保存状态,我们作为另一个入口分析
@Override
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
保存所有状态,还是用到FragmentController
Parcelable p = mFragments.saveAllState();
修改状态
mStateSaved = true;
所有状态关联上循环,
SparseArray mActive;
之前用的HashMap现在优化成SparseArray。 我们用的findFragmentByTag。。都保存在这个地方.
生成了N 个Fragment的所有状态属性,用来保存fragment的成员变量
FragmentState fs = new FragmentState(f);
恢复信息fs 信息会被添上
inal class FragmentState implements Parcelable {
final String mClassName;
final int mIndex;
final boolean mFromLayout;
final int mFragmentId;
final int mContainerId;
final String mTag;
final boolean mRetainInstance;
final boolean mDetached;
final Bundle mArguments;
final boolean mHidden;
Bundle mSavedFragmentState;
Fragment mInstance;
...
}
fragment 树保存,
fs.mSavedFragmentState = saveFragmentBasicState(f); 这里面会保存view树
。。。
Bundle saveFragmentBasicState(Fragment f)
构建了回退栈数组 backStack = new BackStackState[N];
所有栈信息保存在FragmentManagerState
FragmentManagerState fms = new FragmentManagerState();
fms.mActive = active;
fms.mAdded = added;
fms.mBackStack = backStack;
if (mPrimaryNav != null) {
fms.mPrimaryNavActiveIndex = mPrimaryNav.mIndex;
}
fms.mNextFragmentIndex = mNextFragmentIndex;
onSaveInstanceState 中 将信息放入Bundle
FragmentActivity -》onCreate
手机在退出或者旋转 就会调动,那么 会通过FragmentManagerImpl-->restoreAllState 恢复状态。
最终还是经过
// We need to ensure that onDestroy and any other clean up is done
// so move the Fragment up to CREATED, then mark it as being removed, then
// destroy it.
moveToState(f, Fragment.CREATED, 0, 0, false);
f.mRemoving = true;
moveToState(f, Fragment.INITIALIZING, 0, 0, false);
状态恢复入口分析
FragmentActivity.onCreate()
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreSaveState(p);
FragmentManagerImpl.restoreSaveState()把之前保存的数据取回来
moveToState 重新执行fragment生命周期
最后: 分析COMMIT的四种提交方式 基本核心很相似