AndroidX 下的Fragment 源码机制分析

标准的Fragment声明周期

fragment_lifecycle.png

入口分析

从FragmentActivity 开始看 onCreate 等很多分发操作,看下整个核心架构图

FragmentActivity上的所有生命周期相关API都会调用

FragmentController对应的dispatchXXX()

mFragments.dispatchCreate();

mHost.mFragmentManager.dispatchCreate();

Fragment 管理核心结构.png

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 mAdded = new 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 mPendingActions; 集合

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

Fragment核心代码流程.png

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);
    }
}

操作这两个集合,有一个算法

之前是双端链表不断添加删除,现在改成两个集合算法,没有删除操作,并且空间可复用

image.png

大体算法意思,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的四种提交方式 基本核心很相似

你可能感兴趣的:(AndroidX 下的Fragment 源码机制分析)