源码解析Fragment 返回栈原理

本文深入解析Fragment返回栈的工作原理,涉及返回栈中的关键类如BackStackRecord、FragmentManagerImpl及其交互流程。通过事务提交和出栈的源码分析,阐述Fragment在返回栈中的状态管理和生命周期切换,帮助理解Fragment的内部实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列
Fragment (一):Fragment使用详解
Fragment (二):Activity 和Fragment 的异常销毁、状态保存和恢复机制
Fragment (三):源码解析Fragment 返回栈原理

返回栈涉及的类


在看本文前需要熟悉Fragment 的使用,不清楚的可先看:Fragment使用详解

本文源码都是都是v25 的support v4 包下的源码。

基本操作:getFragmentManager().beginTransaction().add(R.id.container, fragment).addToBackStack(null).commit();
getFragmentManager():实际返回值是FragmentManagerImpl 对象。
beginTransaction():实际返回值是BackStackRecord 对象。

  • BackStackRecord.Op
    代表Fragment 事务中的一次操作,如add、remove等。

  • BackStackRecord
    一个BackStackRecord 代表一次Fragment 事务
    BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator 实现了OpGenerator
    Field:
    1、ArrayList<BackStackRecord.Op> mOps:保存一次Fragment 事务的所有Op 操作。
    2、FragmentManagerImpl mManager:保存getFragmentManager() 的返回值。

  • FragmentManagerImpl.OpGenerator
    相当于BackStackRecord。一个OpGenerator 对象能产生相应的一个BackStackRecord 对象,该BackStackRecord 对象可能是OpGenerator 对象本身也可能来自返回栈。

  • FragmentManagerImpl
    Field:
    1、ArrayList<FragmentManagerImpl.OpGenerator> mPendingActions:存放当前尚未执行的所有事务,用于产生mTmpRecords 和mTmpIsPop。
    2、ArrayList<BackStackRecord> mTmpRecords:存放当前尚未执行的所有事务,由mPendingActions 转化而来。
    3、ArrayList<Boolean> mTmpIsPop:mTmpRecords 中对应下标下的事务是否是出栈。
    4、ArrayList<BackStackRecord> mBackStack:返回栈,存放mTmpRecords 中进栈的事务。
    5、ArrayList<Fragment> mAdded:存放前台Fragment,即已调用了add() 但尚未进入返回栈或被被销毁的Fragment。
    6、ArrayList<Fragment> mActive:存放前台Fragment 和返回栈中的Fragment。
    7、ArrayList<Fragment> mTmpAddedFragments:临时的mAdded 。

看源码前先了解下:
1、Fragment 的各种状态:

static final int INITIALIZING = 0;     // Not yet created.销毁。
static final int CREATED = 1;          // Created.没有视图但fragment已创建,比如:fragment处于返回栈中。
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.宿主Activity已创建完毕,就是fragment生命周期已调用到onActivityCreated(),已创建视图。
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.聚焦

事务提交


流程

  1. BackStackRecord:addToBackStack() //若调用则标志事务进栈,否则不进栈。
  2. BackStackRecord:commit()
  3. BackStackRecord:commitInternal()
  4. FragmentManagerImpl:enqueueAction() //BackStackRecord加入mPendingActions。
  5. FragmentManagerImpl:generateOpsForPendingActions() //mPendingActions转换为mTmpRecords 和mTmpIsPop。
  6. FragmentManagerImpl:executeOpsTogether() //遍历mTmpRecords。1、将Op是replace 的替换为多个remove 和一个add。2、执行所有Op,更新mAdded 和mActive。每个事务的最后一个Op时,对mAdded 和mActive 中所有Fragment 切换生命周期到预期的状态,同时,在此过程中对每一个从前台退回到返回栈的Fragment调用它的顶级View 的saveHierarchyState() 保存View状态,对每一个从返回栈出栈变为前台的Fragment调用它的顶级View的restoreHierarchyState() 恢复View状态。

源码

BackStackRecord:

public FragmentTransaction addToBackStack(String name) {
    if (!mAllowAddToBackStack) {
        throw new IllegalStateException(
                "This FragmentTransaction is not allowed to be added to the back stack.");
    }
    mAddToBackStack = true;//
    mName = name;
    return this;
}

public int commit() {
    return commitInternal(false);
}

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);//该BackStackRecord对象加入mPendingActions
    return mIndex;
}

FragmentManagerImpl:

/**
 * Adds an action to the queue of pending actions.
 */
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        checkStateLoss();
    }
    synchronized (this) {
        if (mDestroyed || mHost == null) {
            throw new IllegalStateException("Activity has been destroyed");
        }
        if (mPendingActions == null) {
            mPendingActions = new ArrayList<>();
        }
        mPendingActions.add(action);//
        scheduleCommit();//用UI线程的Handler发送Runnable
    }
}

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

Runnable mExecCommit = new Runnable() {
    @Override
    public void run() {
        execPendingActions();
    }
};

/**
 * Only call from main thread!
 */
public boolean execPendingActions() {
    ensureExecReady(true);

    boolean didSomething = false;
    while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
  //mPendingActions 转换为mTmpRecords 和mTmpIsPop。
        mExecutingActions = true;
        try {
            optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);//优化并处理所有Op
        } finally {
            cleanupExec();
        }
        didSomething = true;
    }

    doPendingDeferredStart();

    return didSomething;
}

/**
 * Adds all records in the pending actions to records and whether they are add or pop
 * operations to isPop. After executing, the pending actions will be empty.
 */
private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
        ArrayList<Boolean> isPop) {
    int numActions;
    synchronized (this) {
        if (mPendingActions == null || mPendingActions.size() == 0) {
            return false;
        }

        numActions = mPendingActions.size();
        for (int i = 0; i < numActions; i++) {
            mPendingActions.get(i).generateOps(records, isPop);
            //若该事务是出栈,则从mBackStack 中取出一个事务即BackStackRecord加入mTmpRecords;
            //否则,将当前action 加入mTmpRecords,若该事务进栈还要添加到mBackStack中。
        }
        mPendingActions.clear();//清空
        mHost.getHandler().removeCallbacks(mExecCommit);
    }
    return numActions > 0;
}

private void optimizeAndExecuteOps(ArrayList<BackStackRecord> records,
        ArrayList<Boolean> isRecordPop) {
    ......

    // Force start of any postponed transactions that interact with scheduled transactions:
    executePostponedTransaction(records, isRecordPop);

    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值