Fragment 源码简要分析

Fragment简析

从Android引入Fragment开始,在Android中使用的场景也越来越多,但是我们会发现Fragment相对于View来说实在坑有点多,这篇主要对Fragment做一个较深一点的分析(太深估计也不太行),主要讨论Fragment与Activity的生命周期如何联动、Activity如何管理Fragment等话题

一、Fragment基本使用以及过程分析

从Fragment创建添加到Activity开始看

    FragmentManager manager=getSupportFragmentManager();//这里最终获得一个FragmentManagerImpl类型的对象
    FragmentTransaction fragmentTransaction=manager.beginTransaction();//开启事务,return new BackStackRecord(this)
    MyFragment myFragment=new MyFragment();
    fragmentTransaction.add(R.id.container,myFragment,"tag");//添加Fragment到Activity
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();//提交事务

简单的说要想添加一个Fragment到FragmentActivity中,我们需要首先获取它的FragmentManager,然后需要开启Fragment事务,接着添加Fragment,最后提交事务让操作生效,一步步来看

首先FragmentManager什么时候被创建

    //获取FragmentManager,其中FragmentActivity中成员变量mFragments类型为FragmentController
    public FragmentManager getSupportFragmentManager() {
        return mFragments.getSupportFragmentManager();
    }
    //FragmentController的成员变量mHost数据类型为FragmentHostCallback
    public FragmentManager getSupportFragmentManager() {
        return mHost.getFragmentManagerImpl();
    }
    //最终返回位于FragmentHostCallBack类中的FragmentManagerImpl的实现对象
    FragmentManagerImpl getFragmentManagerImpl() {
        return mFragmentManager;
    }

从FragmentManager的获取可以看到Activity不通过FragmentManager来管理,而是通过FragmentController来管理,所以再看FragmentController的创建过程如下

    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());//变量声明时创建管理类
    //HostCallback类声明以及构造方法如下,文档中
    class HostCallbacks extends FragmentHostCallback
  
    { public HostCallbacks() { super(FragmentActivity.this); } } //FramentController的创建过程如下 public static final FragmentController createController(FragmentHostCallback
    callbacks) { return new FragmentController(callbacks); } private FragmentController(FragmentHostCallback
    callbacks) { mHost = callbacks;//将HostCallback与之关联 } 
  

从代码来看Activity管理Fragment与FragmentController、HostCallbacks、FragmentManager这三个类息息相关,文档对它们的说明如下

HostCallbacks:继承自FragmentHostCallback,后者是对Fragment的宿主的封装类(任何对象都可能成为Fragment的宿主),典型的宿主是Activity

FragmentController:主要集成FragmentManager的功能,向Fragment的宿主提供管理Fragment的能力

FragmentManager:其实现类FragmentManagerImpl文档说明其为Fragment的容器,充当管理Fragment的角色

next step 看事务的开启

    //直接new 了一个BackStackRecord
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

对于BackStackRecord对象(继承自FragmentTransaction)文档的解释是Entry of an operation on the fragment back stack-fragment返回栈的操作条目,仔细看这个类我们可以发现这个定义了相当多的动作,比如OP_ADD、OP_REPLACE等Fragment的添加、替换等操作,我认为该类是对命令的封装,代表这对于Fragment的一系列操作。同时我们也可以知道一个事务的操作都是被记录在BackStackRecord中,即一个BackStackRecord对象代表着一个事务。

next step-BackStackRecord的add方法添加Fragment,也就是一系列在BackStackRecord上的操作

    public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
        doAddOp(containerViewId, fragment, tag, OP_ADD);//OP_ADD表示添加Fragment的操作
        return this;
    }

    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        final Class fragmentClass = fragment.getClass();
        final int modifiers = fragmentClass.getModifiers();
        //检查Fragment的类声明,不能是匿名类、非共有类、如果是内部类必须是静态的,代码略
        fragment.mFragmentManager = mManager;//这里我们创建的Fragment和FragmentManager进行了绑定
        //如果Fragment已经又tag则不能再添加tag,代码略

        if (containerViewId != 0) {
            //可以看到这种添加方式使得fragment的contanierId和fragmentId成为一个,宿主id
            fragment.mContainerId = fragment.mFragmentId = containerViewId;
        }
        Op op = new Op();//Fragment的操作类
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);//插入到操作的链表中
    }

从上述代码看当我们添加一个Fragment到Activity中时,Fragment不会被立即进入生命周期方法的调用,而是先将Fragment与Activity的FragmentManager进行绑定,然后为添加Fragment中这个操作生成了一个命令对象Op,添加时使用数字来表示对应的操作

next step-可选步骤添加回退栈

    只是简单的置回退状态为true,保存传入的字符串
    public FragmentTransaction addToBackStack(String name) {
        //....
        mAddToBackStack = true;
        mName = name;
        return this;
    }

final step-提交事务

    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);//将事务提交
        return mIndex;
    }
    //如文档所解释将一个任务加入到队列中,同时可以看到BackStackRecord实现了Runnable接口
    public void enqueueAction(Runnable action, boolean allowStateLoss) {
        if (!allowStateLoss) {//首先需要检查Activity状态,以决定是否可以提交
            checkStateLoss();
        }
        synchronized (this) {
            if (mDestroyed || mHost == null) {
                throw new IllegalStateException("Activity has been destroyed");
            }
            if (mPendingActions == null) {
                mPendingActions = new ArrayList
  
   (); } mPendingActions.add(action);//添加任务 if (mPendingActions.size() == 1) {//如果只有当前一个任务 mHost.getHandler().removeCallbacks(mExecCommit);//移除任务队列中的任务,猜测是为了避免死循环 mHost.getHandler().post(mExecCommit);//重新post一个 } } } //该方法必是mExecCommit对象执行的方法,须从主线程来调用 public boolean execPendingActions() { //检查事务是否重复提交,以及调用线程 boolean didSomething = false; while (true) { int numActions; synchronized (this) { //以下取出当前FragmentManager管理的Fragment的事务的操作 if (mPendingActions == null || mPendingActions.size() == 0) { break; } numActions = mPendingActions.size(); if (mTmpActions == null || mTmpActions.length < numActions) { mTmpActions = new Runnable[numActions]; } mPendingActions.toArray(mTmpActions); mPendingActions.clear(); mHost.getHandler().removeCallbacks(mExecCommit); } mExecutingActions = true; for (int i=0; i
   
     Fragment.CREATED) { newState = Fragment.CREATED; } if (f.mRemoving && newState > f.mState) { // While removing a fragment, we can't change it to a higher state. newState = f.mState; } // Defer start if requested; don't allow it to move to STARTED or higher // if it's not already started. if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) { newState = Fragment.STOPPED; } if (f.mState < newState) { //...略 switch (f.mState) { case Fragment.INITIALIZING: if (f.mSavedFragmentState != null) {//首先检查是否为恢复状态 f.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader()); f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray( FragmentManagerImpl.VIEW_STATE_TAG); f.mTarget = getFragment(f.mSavedFragmentState, FragmentManagerImpl.TARGET_STATE_TAG); if (f.mTarget != null) { f.mTargetRequestCode = f.mSavedFragmentState.getInt( FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0); } f.mUserVisibleHint = f.mSavedFragmentState.getBoolean( FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true); if (!f.mUserVisibleHint) { f.mDeferStart = true; if (newState > Fragment.STOPPED) { newState = Fragment.STOPPED; } } } f.mHost = mHost;//这里为Fragment绑定Host f.mParentFragment = mParent; f.mFragmentManager = mParent != null ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl(); f.mCalled = false; f.onAttach(mHost.getContext());//Attch方法调用 if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()"); } if (f.mParentFragment == null) { mHost.onAttachFragment(f); } else { f.mParentFragment.onAttachFragment(f); } if (!f.mRetaining) { f.performCreate(f.mSavedFragmentState);//onCreate方法调用 } else { f.restoreChildFragmentState(f.mSavedFragmentState);//恢复子Fragment状态 f.mState = Fragment.CREATED; } f.mRetaining = false; if (f.mFromLayout) {//初始化时从XML中初始化则立即初始化布局 f.mView = f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState), null, f.mSavedFragmentState);//这里进去可看看到onCreateView方法被调用 if (f.mView != null) { f.mInnerView = f.mView; if (Build.VERSION.SDK_INT >= 11) { ViewCompat.setSaveFromParentEnabled(f.mView, false); } else { f.mView = NoSaveStateFrameLayout.wrap(f.mView); } if (f.mHidden) f.mView.setVisibility(View.GONE); f.onViewCreated(f.mView, f.mSavedFragmentState); } else { f.mInnerView = null; } } case Fragment.CREATED: if (newState > Fragment.CREATED) { if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f); if (!f.mFromLayout) { ViewGroup container = null; if (f.mContainerId != 0) { if (f.mContainerId == View.NO_ID) { throwException(new IllegalArgumentException( "Cannot create fragment " + f + " for a container view with no id")); } //找宿主的View,其中mContainer在FragmentActivity中的onCreate中attach container = (ViewGroup) mContainer.onFindViewById(f.mContainerId); if (container == null && !f.mRestored) { String resName; try { resName = f.getResources().getResourceName(f.mContainerId); } catch (NotFoundException e) { resName = "unknown"; } throwException(new IllegalArgumentException( "No view found for id 0x" + Integer.toHexString(f.mContainerId) + " (" + resName + ") for fragment " + f)); } } f.mContainer = container; f.mView = f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState), container, f.mSavedFragmentState); if (f.mView != null) { f.mInnerView = f.mView; if (Build.VERSION.SDK_INT >= 11) { ViewCompat.setSaveFromParentEnabled(f.mView, false); } else { f.mView = NoSaveStateFrameLayout.wrap(f.mView); } if (container != null) { Animation anim = loadAnimation(f, transit, true, transitionStyle); if (anim != null) { setHWLayerAnimListenerIfAlpha(f.mView, anim); f.mView.startAnimation(anim); } container.addView(f.mView); } if (f.mHidden) f.mView.setVisibility(View.GONE); f.onViewCreated(f.mView, f.mSavedFragmentState); } else { f.mInnerView = null; } } f.performActivityCreated(f.mSavedFragmentState); if (f.mView != null) { f.restoreViewState(f.mSavedFragmentState); } f.mSavedFragmentState = null; } //...一系列生命周期方法的调用 } } else if (f.mState > newState) { //这里是从显示到隐藏的生命周期逻辑,略 } } if (f.mState != newState) { Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; " + "expected state " + newState + " found " + f.mState); f.mState = newState; } } 
   
  

上面的一系列分析来看,我们在启动一个事务去操作Fragment时,实际上当时只是记录一组操作,我们提交时才会真正去做操作,同时Fragment的状态切换的核心函数是moveToState,Fragment的生命周期方法在这里连续执行到指定周期。

二、Fragment如何与Activity的生命周期联动

从上面来看Fragment生命周期即状态切换主要依靠moveToState来,所以这里一个猜想就是Activity在其生命周期方法中做Fragment的状态切换

首先看FragmentActivity的onCreate方法

protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);//首先FragmentController绑定相应的host

        super.onCreate(savedInstanceState);

        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            mFragments.restoreLoaderNonConfig(nc.loaders);
        }
        if (savedInstanceState != null) {//如果是Activity回收重新恢复的情况
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            //重新恢复Fragment的状态
            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
            //....略
        }
        //...略
        mFragments.dispatchCreate();
    }

接着在看onResume以及onStop方法

    protected void onResume() {
        super.onResume();
        mHandler.sendEmptyMessage(MSG_RESUME_PENDING);//这里最终会调用Fragment的生命周期切换方法
        mResumed = true;
        mFragments.execPendingActions();
    }

    protected void onStop() {
        super.onStop();
        mStopped = true;
        mHandler.sendEmptyMessage(MSG_REALLY_STOPPED);
        mFragments.dispatchStop();//这里是Fragment的状态切换
    }

所以这里就很简单,Acitivity在自己的生命周期内通过Fragment的管理对象去切换Fragment的状态,从而使得Activity与Fragment生命周期的联动

三、Fragment的恢复过程

这里主要看一个Activity被销毁之后Fragment如何恢复

主要看销毁之前会存哪些数据

    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Parcelable p = mFragments.saveAllState();//存储数据
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
        //略...
    }
    //数据存储操作
    Parcelable saveAllState() {
        // 执行某些未完成的任务
        execPendingActions();
        //...
        if (mActive == null || mActive.size() <= 0)="" {="" return="" null;="" }="" first="" collect="" all="" active="" fragments.="" int="" n="mActive.size();" fragmentstate[]="" fragmentstate[n];="" boolean="" havefragments="false;" for="" (int="" i="0;" i
  
    Fragment.INITIALIZING && fs.mSavedFragmentState == null) { fs.mSavedFragmentState = saveFragmentBasicState(f);//这里做关于Fragment的View的状态恢复 //.... } else { fs.mSavedFragmentState = f.mSavedFragmentState; } //... } } //... int[] added = null; BackStackState[] backStack = null; //BackStack状态保存... FragmentManagerState fms = new FragmentManagerState(); fms.mActive = active;//保存Fragment状态 fms.mAdded = added; fms.mBackStack = backStack; return fms; } 
   
  

上面的方法可以看出主要会存Fragment的状态信息、回退栈、View信息之类的关键数据,然后相应的会在onCreate的方法中恢复,所以很多时候如果我们不处理关于Activity的回收恢复的逻辑,当我们使用的Fragment的时候每次只是在Activity中去直接new 一个Fragment很有可能我们的Activity恢复之后会有多个同样的Fragment同时存在的情况,同时由于恢复跳过一些生命周期方法则host attach不到则会出现一些错误

    原文作者:Android源码分析
    原文地址: https://juejin.im/entry/583a9d01a22b9d006a84a94b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞