Fragment相关源码解析二——生命周期

本文详细探讨了Fragment的生命周期,包括Fragment的mState、FragmentManagerImpl的mCurState、FragmentActivity的生命周期影响,以及BackStackRecord的run()方法。文章指出,Fragment的状态改变可能由FragmentActivity的生命周期回调或BackStackRecord的提交引起。FragmentManagerImpl的moveToState()方法是管理Fragment生命周期的关键,文章分析了其工作原理和状态转移过程。此外,还讨论了addToBackStack()、setRetainInstance(true)的影响以及直接添加Fragment可能引发的问题。
摘要由CSDN通过智能技术生成

上次说到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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值