Fragment相关源码解析一——FragmentManagerImpl和BackStackRecord

原来一直只是使用Fragment,除了对一些常用API很熟悉外,对Fragment的内部原理还是不清楚,索性花了几天的时间,去阅读了Fragment相关的源码,从整体上对Fragment的框架有了一定深度的认识。当然,Fragment相关的类很多,Fragment内部的成员也很多,我目前还无法弄清楚Fragment的每一个细节,但整体上的正确认识有助于我们对细节的把握,也能对问题的查找、定位以及解决起到指导作用。这篇文章我准备先从Fragment被添加到Activity中的过程入手,观察一些相关的类和调用流程,然后针对一些具体的问题,在源码中找到解释做出总结。

FragmentActivity、HostCallbacks和FragmentController

从我们平常使用的动态添加Fragment说起,看一下其中是哪些类在起作用。

MyFragment f = new MyFragment();
getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content, f)
                .commit();

其中getSupportFragmentManager()方法返回了一个FragmentManager对象。

先来看看mFragments这个成员,它是一个FragmentController对象。创建的时候还传入了一个继承FragmentHostCallback类的HostCallbacks对象。

    //FragmentActivity.java
    public FragmentManager getSupportFragmentManager() {
        return mFragments.getSupportFragmentManager();
    }

    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

先来看下这个HostCallbacks对象,初始化的时候传入了调用FragmentController.createController(new HostCallbacks())的FragmentActivity的实例的引用。

//HostCallbacks.java
        public HostCallbacks() {
            super(FragmentActivity.this /*fragmentActivity*/);
        }

构造器中只调用了父类的构造器,继续看HostCallbacks的父类FragmentHostCallback。构造器利用传进来的FragmentActivity的引用,为自己的成员变量赋值,可以看到,这个类的实例不仅持有了Activity的引用,还持有它的context,handler等。重点关注下mFragmentManager这个成员,它在HostCallbacks初始化的时候也初始化,是一个 FragmentManagerImpl对象。

    //FragmentHostCallback.java
    FragmentHostCallback(FragmentActivity activity) {
            this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
        }

    FragmentHostCallback(Activity activity, Context context, Handler handler,
                int windowAnimations) {
            mActivity = activity;
            mContext = context;
            mHandler = handler;
            mWindowAnimations = windowAnimations;
        }
    private final Activity mActivity;
    final Context mContext;
    private final Handler mHandler;
    final int mWindowAnimations;
    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
    /** The loader managers for individual fragments [i.e. Fragment#getLoaderManager()] */
    private SimpleArrayMap mAllLoaderManagers;
    /** Whether or not fragment loaders should retain their state */
    private boolean mRetainLoaders;
    /** The loader manger for the fragment host [i.e. Activity#getLoaderManager()] */
    private LoaderManagerImpl mLoaderManager;
    private boolean mCheckedForLoaderManager;
    /** Whether or not the fragment host loader manager was started */
    private boolean mLoadersStarted;

再回到开头final FragmentController mFragments = FragmentController.createController(new HostCallbacks());这句话,mFragments(FragmentController)初始化的时候传入了一个HostCallbacks对象,这个对象似乎拥有Activity的很多信息并且具有它的引用。接着进入createController(FragmentHostCallback< ? > callbacks)方法,它初始化了一个FragmentController对象,而且把传入的HostCallbacks对象赋值给了自己的成员mHost,也就是说这个对象也持有了Activity的引用和一些信息。

//FragmentController.java
public static final FragmentController createController(FragmentHostCallback callbacks) {
        return new FragmentController(callbacks);
    }

private FragmentController(FragmentHostCallback callbacks) {
        mHost = callbacks;
    }

现在出现了FragmentActivity、HostCallbacks、FragmentController,后面两个类的实例都持有了FragmentActivity实例的引用。

我们再回到FragmentActivity#getSupportFragmentManager(),它调用了mFragments的getSupportFragmentManager()方法。

//FragmentController.java
public FragmentManager getSupportFragmentManager() {
        return mHost.getFragmentManagerImpl();
    }

返回的就是上面说到重点关注的成员mFragmentManager,它是一个FragmentManagerImpl对象。

//FragmentHostCallback.java
    FragmentManagerImpl getFragmentManagerImpl() {
        return mFragmentManager;
    }

这个内部类继承了FragmentManager类。

final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory

到这里,getsupportFragmentmanager()方法看完了,引出了HostCallbacks类,FragmentController类。

接下来看beginTransaction()返回了一个BackStackRecord对象,这个对象继承于FragmentTransaction,看来后面的操作都和BackStackRecord对象有关了。

//FragmentManager.java
@Override
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

到目前为止,我们知道getsupportFragmentmanager()返回了一个FragmentManagerImpl,它继承了FragmentManager, beginTransaction()返回了一个BackStackRecord对象,它继承了FragmentTransaction。FragmentController内部持有HostCallbacks(持有FragmentActivity的很多信息,还持有一个重要的类FragmentManagerImpl),FragmentActivity的对Fragment的操作都是转交给FragmentController去处理,而FragmentController内部也是调用HostCallbacks持有的FragmentManagerImpl去进行实际的操作。看来FragmentManagerImpl这个类是和Fragment打交道的类。而BackStackRecord也是FragmentManagerImpl操作的一个工具。

BackStackRecord和FragmentManagerImpl

BackStackRecord内部有一个Op静态内部类,这个类含有两个Op引用,所以可以构成双向链表(双向链表结构有助于增加被添加到回退栈的BackStackRecord对象的回退效率)。一个Op内部维护一个cmd操作数,一个fragment,还有一些动画相关的参数。

//BackStackRecord.java   
static final class Op {
        Op next;
        Op prev;
        int cmd;
        Fragment fragment;
        int enterAnim;
        int exitAnim;
        int popEnterAnim;
        int popExitAnim;
        ArrayList removed;
    }

我们看一下得到BackStackRecord后一些典型操作,其实最终都是创建了一个新的Op对象,然后为cmd和fragment赋值并执行了addOp(op).

    //BackStackRecord.java  
    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 (tag != null) {
            if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
                throw new IllegalStateException("Can't change tag of fragment "
                        + fragment + ": was " + fragment.mTag
                        + " now " + tag);
            }
            fragment.mTag = tag;
        }

        if (containerViewId != 0) {
            if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
                throw new IllegalStateException("Can't change container ID of fragment "
                        + fragment + ": was " + fragment.mFragmentId
                        + " now " + containerViewId);
            }
            fragment.mContainerId = fragment.mFragmentId = containerViewId;
        }

        Op op = new Op();
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);
    }


    public FragmentTransaction remove(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_REMOVE;
        op.fragment = fragment;
        addOp(op);

        return this;
    }


    public FragmentTransaction hide(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_HIDE;
        op.fragment = fragment;
        addOp(op);

        return this;
    }

addOp(op) 实际是把op加入双向链表尾部,一个BackStackRecord对象内部可能有肯多次对Fragment的操作,每一次操作都对应一个Op对象,并把Op对象加入双向链表中。

//BackStackRecord.java     
    void addOp(Op op) {
        if (mHead == null) {
            mHead = mTail = op;
        } else {
            op.prev = mTail;
            mTail.next = op;
            mTail = op;
        }
        op.enterAnim = mEnterAnim;
        op.exitAnim = mExitAnim;
        op.popEnterAnim = mPopEnterAnim;
        op.popExitAnim = mPopExitAnim;
        mNumOp++;
    }

一个BackStackRecord对象的重要成员成员和Op的cmd的值如下:

//BackStackRecord.java
    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;

    final FragmentManagerImpl mManager;
    Op mHead;
    Op mTail;
    int mNumOp;
    int mEnterAnim;
    int mExitAnim;
    int mPopEnterAnim;
    int mPopExitAnim;
    int mTransition;
    int mTransitionStyle;
    boolean mAddToBackStack;
    boolean mAllowAddToBackStack = true;
    String mName;
    boolean mCommitted;
    int mIndex = -1;

一个BackStackRecord中可能包含多个操作,每一个操作都以一个Op对象的形式保存在BackStackRecord双向链表中。当对Fragment操作完了之后,最后一步是执行BackStackRecord的commit()方法。

    //BackStackRecord.java
    public int commit() {
        return commitInternal(false);
    }
    int commitInternal(boolean allowStateLoss) {
        if (mCommitted) throw new IllegalStateException("commit already called");
        if (FragmentManagerImpl.DEBUG) {
            Log.v(TAG, "Commit: " + this);
            LogWriter logw = new LogWriter(TAG);
            PrintWriter pw = new PrintWriter(logw);
            dump("  ", null, pw, null);
        }
        //一个BackStackRecord对象只能被提交一次
        mCommitted = true;
        if (mAddToBackStack) {
            //大致过程是保存在了mManager的一个ArrayList中,为该BackStackRecord分配唯一index
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

最终调用了FragmentManagerImpl的enqueueAction(Runnable action, boolean allowStateLoss) ,回看BackStackRecord类声明才发现它实现了Runnable接口(那么它的run() 方法肯定很重要)。

   //FragmentManagerImpl.java
    public void enqueueAction(Runnable 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();
            }
            //一个ArrayList成员,添加了传入的BackStackRecord对象
            mPendingActions.add(action);
            //可能会post一个mExecCommit,这里的mHost.getHandler()获得的就是Activity的Handler
            //这里说一下,FragmentManagerImpl中mHost赋值的时机是在Activity的onCreate()方法被调用时
            if (mPendingActions.size() == 1) {
                mHost.getHandler().removeCallbacks(mExecCommit);
                mHost.getHandler().post(mExecCommit);
            }
        }
    }

mExecCommit是一个Runnable成员,被post之后进入主线程的队列,会执行execPendingActions()方法

    //FragmentManagerImpl.java    
    Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    };

    public boolean execPendingActions() {
        if (mExecutingActions) {
            throw new IllegalStateException("Recursive entry to executePendingTransactions");
        }

        if (Looper.myLooper() != mHost.getHandler().getLooper()) {
            throw new IllegalStateException("Must be called from main thread of process");
        }

        boolean didSomething = false;

        while (true) {
            int numActions;

            synchronized (this) {
                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;
            //依次执行mPendingActions中BackStackRecord的run方法
            for (int i=0; i

从beginTransaction()开始,我们获得了一个BackStackRecord对象,接着执行一系列对Fragment的操作,在BackStackRecord内部表现为新建一系列Op对象并为它们的cmd和fragment成员赋相应的值,然后添加到双向链表中。commit()之后,BackStackRecord对象作为一个Runnable被添加到了FragmentManagerImpl的mPendingActions中,并在合适的时机会在主线程中执行BackStackRecord的run()。 也就是说commit() 之后,FragmentManagerImpl管理着BackStackRecord,并交由主线程执行BackStackRecord的run()。

第一篇就说到这里,接下来会具体分析BackStackRecord的run()方法和FragmentManagerImpl的moveToState(5参数)方法,来看看Fragment的生命周期到底是如何和Activity交互的,最后还会针对Fragment的状态保存相关问题在源码中找寻答案。

你可能感兴趣的:(Android基础)