Fragment 的生命周期来龙去脉

本文详细探讨了Fragment的生命周期,从FragmentActivity的onCreate()开始,解析了Fragment如何通过FragmentManager与Activity生命周期关联。文章重点分析了commit()操作如何触发Fragment的启动,包括add()方法、doAddOp()、moveToState()的执行流程,以及Fragment的销毁过程。通过源码阅读,揭示了Fragment生命周期管理的内在机制。
摘要由CSDN通过智能技术生成

Fragment的生命周期我们都不陌生,但是其如何利用FragmentManager从Activity生命周期挂载而来的呢,尤其是看了glide源码后,发现其巧妙的利用了FragmentManager来绑定自己的生命周期,那么为了更清晰的深入理解,一起来看下6.0的源码是如何处理的。

FragmentActivity

  • 1.从启动一个FragmentActivity开始。从onCreate()方法中
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

@SuppressWarnings("deprecation")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    mFragments.attachHost(null /*parent*/);
    super.onCreate(savedInstanceState);

    NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
    if (nc != null) {
        mFragments.restoreLoaderNonConfig(nc.loaders);
    }
    if (savedInstanceState != null) {
        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
    }
    mFragments.dispatchCreate();
}
  • 1.1 重点关注一下 mFragments 的操作。当前的mFragments其实是FragmentController,而FragmentHostCallback在FragmentController初始化时进行初始化,在FragmentHostCallback中可以拿到FragmentManager的子类FragmentManagerImpl。继续看FragmentController的代码
//FragmentController初始化CallBack
 public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
        return new FragmentController(callbacks);
}

private FragmentController(FragmentHostCallback<?> callbacks) {
        mHost = callbacks;
}

public void attachHost(Fragment parent) {
        mHost.mFragmentManager.attachController(
                mHost, mHost /*container*/, parent);
}

public void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
        mHost.mFragmentManager.restoreAllState(state, nonConfig);
}

public void dispatchCreate() {
        mHost.mFragmentManager.dispatchCreate();
}
  • 1.2当前的操作其实都是对FragmentManager进行操作,继续看FragmentManagerImpl代码
// 初始化赋值操作
public void attachController(FragmentHostCallback host,
            FragmentContainer container, Fragment parent) {
        if (mHost != null) throw new IllegalStateException("Already attached");
        mHost = host;
        mContainer = container;
        mParent = parent;
}

void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
    ......
    if (nonConfig != null) {
            List<Fragment> nonConfigFragments = nonConfig.getFragments();
            childNonConfigs = nonConfig.getChildNonConfigs();
            final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
            for (int i = 0; i < count; i++) {
                Fragment f = nonConfigFragments.get(i);
                if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f);
                FragmentState fs = fms.mActive[f.mIndex];
                fs.mInstance = f;
                f.mSavedViewState = null;
                f.mBackStackNesting = 0;
                f.mInLayout = false;
                f.mAdded = false;
                f.mTarget = null;
                if (fs.mSavedFragmentState != null) {
                    fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
                    f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
                            FragmentManagerImpl.VIEW_STATE_TAG);
                    f.mSavedFragmentState = fs.mSavedFragmentState;
                }
            }
        }


        // Build the full list of active fragments, instantiating them from
        // their saved state.
        mActive = new ArrayList<>(fms.mActive.length); 
        // 注意,后面会用到
    ...
}

public void dispatchCreate() {
        mStateSaved = false;
        mExecutingActions = true;
        moveToState(Fragment.CREATED, false);
        mExecutingActions = false;
}
  • 1.3 以上,attachController() 只是简单的初始化的赋值操作,并无对生命周期相关的,继续看restoreAllState(),同样的初始化的重置操作,这里
    mActive = new ArrayList(fms.mActive.length)初始化了一个空的mActive的list。继续看dispatchCreate(),其中moveToState
    void moveToState(int newState, boolean always) {
        if (mHost == null && newState != Fragment.INITIALIZING) {
            throw new IllegalStateException("No activity");
        }

        if (!always && newState == mCurState) {
            return;
        }

        mCurState = newState;

        if (mActive != null) {
            boolean loadersRunning = false;

            // Must add them in the proper order. mActive fragments may be out of order
            if (mAdded != null) {
                final int numAdded = mAdded.size();
                for (int i = 0; i < numAdded; i++) {
                    Fragment f = mAdded.get(i);
                    moveFragmentToExpectedState(f);
                    if (f.mLoaderManager != null) {
                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                    }
                }
            }

            // Now iterate through all active fragments. These will include those that are removed
            // and detached.
            final int numActive = mActive.size();
            for (int i = 0; i < numActive; i++) {
                Fragment f = mActive.get(i);
                if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
                    moveFragmentToExpectedState(f);
                    if (f.mLoaderManager != null) {
                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                    }
                }
            }

            if (!loadersRunning) {
                startPendingDeferredFragments();
            }

            if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
                mHost.onSupportInvalidateOptionsMenu();
                mNeedMenuInvalidate = false;
            }
        }
    }
  • 1.4 moveToState() 其实是更新FragmentManager的状态至Fragment,但是当前并无Fragment,mActive在restoreAllState()初始化出来后只是个空的list,因此并没有实质的操作。至此FragmentActivity onCreate()都是初始化的操作。

  • 2 Fragment的真正启动是当我们调用FragmentManager.beginTransaction().add(fragmet).commit()时触发。看下代码

public abstract class FragmentTransaction {
   
    ......
    public abstract int commit();

    /**
     * Calls {@link #add(int, Fragment, String)} with a 0 containerViewId.
     */
    public abstract FragmentTransaction add(Fragment fragment, String tag);

    /**
     * Calls {@link #add(int, Fragment, String)} with a null tag.
     */
    public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment);

    public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment,
            @Nullable String tag);
    ......
    }
  • 2.1 抽象类FragmentTransaction,这里有个add(Fragment fragment, String tag)方法,添加一个Fragment,只设置tag,不设置viewId,说白了添加一个不妨碍业务的空Fragment方法,这是glide的绑定生命周期的一个点。继续看实现类
final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, Runnable {
   
    ...
     public FragmentTransaction add(int containerViewId, Fragment fragment) {
        doAddOp(containerViewId, fragment, null, OP_ADD);
        return this;
    }

    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        fragment.mFragmentManager = mManager;

        if
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值