Fragment源码分析

来源:互联网 发布:网络安全法的争议内容 编辑:程序博客网 时间:2024/06/05 06:38

转载请标明出处:http://blog.csdn.net/shensky711/article/details/53171248
本文出自: 【HansChen的博客】

概述

Fragment表示 Activity 中的行为或用户界面部分。您可以将多个 Fragment 组合在一个 Activity 中来构建多窗格 UI,以及在多个 Activity 中重复使用某个 Fragment。您可以将 Fragment 视为 Activity 的模块化组成部分,它具有自己的生命周期,能接收自己的输入事件,并且您可以在 Activity 运行时添加或移除 Fragment。
Fragment 必须始终嵌入在 Activity 中,其生命周期直接受宿主 Activity 生命周期的影响。 例如,当 Activity 暂停时,其中的所有 Fragment 也会暂停;当 Activity 被销毁时,所有 Fragment 也会被销毁。 不过,当 Activity 正在运行(处于已恢复生命周期状态)时,您可以独立操纵每个 Fragment,如添加或移除它们。 当您执行此类 Fragment 事务时,您也可以将其添加到由 Activity 管理的返回栈 — Activity 中的每个返回栈条目都是一条已发生 Fragment 事务的记录。 返回栈让用户可以通过按返回按钮撤消 Fragment 事务(后退)。

当您将 Fragment 作为 Activity 布局的一部分添加时,它存在于 Activity 视图层次结构的某个 ViewGroup 内部,并且 Fragment 会定义其自己的视图布局。您可以通过在 Activity 的布局文件中声明Fragment,将其作为 <fragment> 元素插入您的 Activity 布局中,或者通过将其添加到某个现有 ViewGroup,利用应用代码进行插入。不过,Fragment 并非必须成为 Activity 布局的一部分;您还可以将没有自己 UI 的 Fragment 用作 Activity 的不可见工作线程。

本文将通过分析源码,对 Fragment 的创建、销毁以及生命周期做一个更深入的认识。

建议读者在看这篇文章的时候,先看下Fragment事务管理源码分析,对Fragment管理类先有一个比较清楚的认识。

分析入口

    /**     * 构造并显示Fragment     *     * @param containerViewId 容器控件id     * @param clz             Fragment类     */    protected void showFragment(@IdRes int containerViewId, Class<? extends Fragment> clz) {        FragmentManager fm = getFragmentManager();        FragmentTransaction ft = fm.beginTransaction();//开始事务管理        try {            Fragment f = clz.newInstance();            ft.add(containerViewId, f, clz.getName());//添加操作            ft.commit();//提交事务        } catch (Exception e) {            e.printStackTrace();        }    }

上面的代码就是动态地往containerViewId里添加一个Fragment并让它显示出来,可以看到,这个涉及到Fragment的事务管理,详细可以参考Fragment事务管理源码分析,这里就不再阐述了。

代码分析

BackStackRecord#run

调用了commit之后,真正执行的地方是在BackStackRecord的run方法:

    public void run() {        ......        if (mManager.mCurState >= Fragment.CREATED) {            SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();            SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();            calculateFragments(firstOutFragments, lastInFragments);            beginTransition(firstOutFragments, lastInFragments, false);        }        //遍历链表,根据cmd事务类型依次处理事务        Op op = mHead;        while (op != null) {            switch (op.cmd) {                case OP_ADD: {                    //添加一个新的Fragment                    Fragment f = op.fragment;                    f.mNextAnim = op.enterAnim;                    mManager.addFragment(f, false);                }                break;                case OP_REPLACE: {                    Fragment f = op.fragment;                    int containerId = f.mContainerId;                    if (mManager.mAdded != null) {                        for (int i = mManager.mAdded.size() - 1; i >= 0; i--) {                            Fragment old = mManager.mAdded.get(i);                            if (old.mContainerId == containerId) {                                if (old == f) {                                    op.fragment = f = null;                                } else {                                    if (op.removed == null) {                                        op.removed = new ArrayList<Fragment>();                                    }                                    op.removed.add(old);                                    old.mNextAnim = op.exitAnim;                                    if (mAddToBackStack) {                                        old.mBackStackNesting += 1;                                    }                                    mManager.removeFragment(old, mTransition, mTransitionStyle);                                }                            }                        }                    }                    if (f != null) {                        f.mNextAnim = op.enterAnim;                        mManager.addFragment(f, false);                    }                }                break;                case OP_REMOVE: {                    Fragment f = op.fragment;                    f.mNextAnim = op.exitAnim;                    mManager.removeFragment(f, mTransition, mTransitionStyle);                }                break;                case OP_HIDE: {                    Fragment f = op.fragment;                    f.mNextAnim = op.exitAnim;                    mManager.hideFragment(f, mTransition, mTransitionStyle);                }                break;                case OP_SHOW: {                    Fragment f = op.fragment;                    f.mNextAnim = op.enterAnim;                    mManager.showFragment(f, mTransition, mTransitionStyle);                }                break;                case OP_DETACH: {                    Fragment f = op.fragment;                    f.mNextAnim = op.exitAnim;                    mManager.detachFragment(f, mTransition, mTransitionStyle);                }                break;                case OP_ATTACH: {                    Fragment f = op.fragment;                    f.mNextAnim = op.enterAnim;                    mManager.attachFragment(f, mTransition, mTransitionStyle);                }                break;                default: {                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);                }            }            op = op.next;        }        mManager.moveToState(mManager.mCurState, mTransition,                mTransitionStyle, true);        if (mAddToBackStack) {            mManager.addBackStackState(this);        }    }

因为我们调用的是add操作,所以执行的代码片段是:

    case OP_ADD: {        Fragment f = op.fragment;        f.mNextAnim = op.enterAnim;        mManager.addFragment(f, false);    }    break;

参数解释:

  • op.fragment:showFragment中创建的Fragment实例,并且现在Fragment的mTag、mFragmentId、mContainerId已被初始化过了
  • op.enterAnim:入场动画,可以先不管
  • mManager:FragmentManagerImpl实例

FragmentManagerImpl#addFragment

    public void addFragment(Fragment fragment, boolean moveToStateNow) {        //已添加的Fragment列表        if (mAdded == null) {            mAdded = new ArrayList<Fragment>();        }        //设置Fragment的mIndex,并把Fragment添加到mActive列表        makeActive(fragment);        //判断是否被detach。默认为false        if (!fragment.mDetached) {            if (mAdded.contains(fragment)) {                throw new IllegalStateException("Fragment already added: " + fragment);            }            //把Fragment添加到mAdded列表            mAdded.add(fragment);            //设置Fragment标记位            fragment.mAdded = true;            fragment.mRemoving = false;            //判断是否需要刷新菜单            if (fragment.mHasMenu && fragment.mMenuVisible) {                mNeedMenuInvalidate = true;            }            //在这次分析中moveToStateNow为false,moveToState方法在本方法外层方法中调用            if (moveToStateNow) {                moveToState(fragment);            }        }    }

addFragment里面把Fragment加入mActive和mAdded列表,并且设置标记为fragment.mAdded为true,fragment.mRemoving为false。
执行完ADD操作后,执行moveToState,moveToState顾名思义,就是把Fragment变为某种状态

    //mManager.mCurState的状态很重要,我们下面会分析它现在处于什么状态    mManager.moveToState(mManager.mCurState, mTransition,            mTransitionStyle, true);    //添加本次操作到回退栈中    if (mAddToBackStack) {        mManager.addBackStackState(this);    }

Fragment状态

我们知道Fragment的生命周期是依赖于Activity的,比如Activity处于onResume,那么Fragment也会处于onResume状态,这里的参数mManager.mCurState对应的状态有:

    static final int INVALID_STATE = -1;   // Invalid state used as a null value.    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.

mCurState的初始状态是Fragment.INITIALIZING,那么在BackStackRecord中调用moveToState的时候,mCurState是什么值呢?它是会受Activity生命周期影响而变化的,我们来看下FragmentActivity的代码

    @SuppressWarnings("deprecation")    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        //绑定FragmentManager        mFragments.attachHost(null /*parent*/);        super.onCreate(savedInstanceState);        ... ...        //分发Fragment的create事件        mFragments.dispatchCreate();    }
    public void dispatchCreate() {        mHost.mFragmentManager.dispatchCreate();    }    public void dispatchCreate() {        mStateSaved = false;        //注意这里设置了新的state        moveToState(Fragment.CREATED, false);    }    void moveToState(int newState, boolean always) {        moveToState(newState, 0, 0, always);    }    void moveToState(int newState, int transit, int transitStyle, boolean always) {        ... ...        //给mCurState赋值        mCurState = newState;        ... ...    }

在onCreate中把mCurState变为Fragment.CREATED状态了,Activity的其他生命周期方法回调的时候,也会改变这个状态,大致整理如下:

  • onCreate:Fragment.CREATED
  • onStart:Fragment.ACTIVITY_CREATED–>Fragment.STARTED (Fragment.ACTIVITY_CREATED只会在Activity创建之后触发一次,Fragment.STARTED每次onStart的时候都会触发)
  • onResume:Fragment.RESUMED
  • onPause:Fragment.STARTED
  • onStop:Fragment.STOPPED
  • onDestroy:Fragment.INITIALIZING

下面是一张状态迁移图:
这里写图片描述

所以随着Activity生命周期的推进,Activity内所有Fragment的生命周期也会跟着推进。从Activity创建到显示出来,最后会处于onResume状态,那么我们这次就直接分析当前Activity处于onResume调用之后的情形好了。所以假定现在mCurState为Fragment.RESUMED

让我们继续跟踪FragmentManagerImpl

FragmentManagerImpl#moveToState

    void moveToState(int newState, int transit, int transitStyle, boolean always) {        if (mHost == null && newState != Fragment.INITIALIZING) {            throw new IllegalStateException("No activity");        }        if (!always && mCurState == newState) {            return;        }        mCurState = newState;        if (mActive != null) {            boolean loadersRunning = false;            //遍历所有Active状态的Fragment,改变所有Fragment的状态            for (int i=0; i<mActive.size(); i++) {                Fragment f = mActive.get(i);                if (f != null) {                    //关键代码                    moveToState(f, newState, transit, transitStyle, false);                    if (f.mLoaderManager != null) {                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();                    }                }            }            if (!loadersRunning) {                startPendingDeferredFragments();            }            //让Activity刷新Menu            if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {                mHost.onInvalidateOptionsMenu();                mNeedMenuInvalidate = false;            }        }    }

设置最新的mCurState状态,通过上面的分析,我们知道newState等于Fragment.RESUMED。遍历mActive列表中保存的Fragment,改变Fragment状态,这里又调用了一个moveToState方法,这个方法就是真正回调Fragment生命周期的地方

    void moveToState(Fragment f, int newState, int transit, int transitionStyle,            boolean keepActive) {        // Fragments被detach或Fragment没有添加到mAdded列表的话,设置目标Fragment的新状态为CREATED状态,此次分析中不会进入这个分支        if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {            newState = Fragment.CREATED;        }        //此次分析中f.mRemoving为false        if (f.mRemoving && newState > f.mState) {            // While removing a fragment, we can't change it to a higher state.            newState = f.mState;        }        // 是否延时启动        if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {            newState = Fragment.STOPPED;        }        if (f.mState < newState) {            //此次命中的分支            ......            //根据Fragment当前的状态,选择case的分支。需要注意的是,这里的switch case是没有break语句的。这种设计可以让Fragment把自身的状态依次推进到目标状态            switch (f.mState) {                case Fragment.INITIALIZING:                    if (f.mSavedFragmentState != null) {                        ......                    }                    f.mHost = mHost;                    //mParent是在FragmentActivity的onCreate方法中调用attachHost传进来的,传进来的是空值                    f.mParentFragment = mParent;                    f.mFragmentManager = mParent != null                            ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();                    f.mCalled = false;                    //【Fragment生命周期】onAttach回调,里面会把mCalled设置为true                    f.onAttach(mHost.getContext());                    if (!f.mCalled) {                        throw new SuperNotCalledException("Fragment " + f                                + " did not call through to super.onAttach()");                    }                    if (f.mParentFragment == null) {                        //让Activity可以监听到Fragment的attach                        mHost.onAttachFragment(f);                    } else {                        f.mParentFragment.onAttachFragment(f);                    }                    //f.mRetaining默认为false                    if (!f.mRetaining) {                        //关键代码,内部会调用【Fragment生命周期】onCreate                        f.performCreate(f.mSavedFragmentState);                    } else {                        f.restoreChildFragmentState(f.mSavedFragmentState, true);                        f.mState = Fragment.CREATED;                    }                    f.mRetaining = false;                    //Fragment是否定义在Layout文件的<fragment>标签中的,本次栗子为代码动态添加Fragment,所以为false                    if (f.mFromLayout) {                        // For fragments that are part of the content view                        // layout, we need to instantiate the view immediately                        // and the inflater will take care of adding it.                        f.mView = f.performCreateView(f.getLayoutInflater(                                f.mSavedFragmentState), null, f.mSavedFragmentState);                        if (f.mView != null) {                            f.mView.setSaveFromParentEnabled(false);                            if (f.mHidden) f.mView.setVisibility(View.GONE);                            f.onViewCreated(f.mView, f.mSavedFragmentState);                        }                    }                    //注意,这里没有break                case Fragment.CREATED:                    if (newState > Fragment.CREATED) {                        if (!f.mFromLayout) {                            //开始创建Fragment的view                            ViewGroup container = null;                            if (f.mContainerId != 0) {                                if (f.mContainerId == View.NO_ID) {                                    throwException(new IllegalArgumentException(""));                                }                                //调用Activity的findViewById方法查找控件                                container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);                                if (container == null && !f.mRestored) {                                    ......                                }                            }                            f.mContainer = container;                            //关键代码,内部会调用【Fragment生命周期】onCreateView,并返回Fragment中new出的视图                            f.mView = f.performCreateView(f.getLayoutInflater(                                    f.mSavedFragmentState), container, f.mSavedFragmentState);                            if (f.mView != null) {                                f.mView.setSaveFromParentEnabled(false);                                if (container != null) {                                    //设置入场动画                                    Animator anim = loadAnimator(f, transit, true,                                            transitionStyle);                                    if (anim != null) {                                        anim.setTarget(f.mView);                                        setHWLayerAnimListenerIfAlpha(f.mView, anim);                                        anim.start();                                    }                                    //把Fragment的view加入到父控件                                    container.addView(f.mView);                                }                                if (f.mHidden) f.mView.setVisibility(View.GONE);                                //【Fragment生命周期】onViewCreated回调                                f.onViewCreated(f.mView, f.mSavedFragmentState);                            }                        }                        //关键代码,内部会调用【Fragment生命周期】onActivityCreated                        f.performActivityCreated(f.mSavedFragmentState);                        if (f.mView != null) {                            f.restoreViewState(f.mSavedFragmentState);                        }                        f.mSavedFragmentState = null;                    }                case Fragment.ACTIVITY_CREATED:                    if (newState > Fragment.ACTIVITY_CREATED) {                        f.mState = Fragment.STOPPED;                    }                case Fragment.STOPPED:                    if (newState > Fragment.STOPPED) {                        if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);                        //关键代码,内部会调用【Fragment生命周期】onStart                        f.performStart();                    }                case Fragment.STARTED:                    if (newState > Fragment.STARTED) {                        //关键代码,内部会调用【Fragment生命周期】onResume                        f.performResume();                        // Get rid of this in case we saved it and never needed it.                        f.mSavedFragmentState = null;                        f.mSavedViewState = null;                    }            }        } else if (f.mState > newState) {            //state降级处理            ......        }        if (f.mState != newState) {            f.mState = newState;        }    }

这段代码逻辑还是比较长,我把注释写在代码里了。可以看到,这个代码写得很巧妙,通过switch case控制,可以一层一层地把Fragment的生命周期推进下去,比如当前fragnemt的state是Fragment.STARTED,那么它就只会执行performResume,如果Fragment的状态是Fragment.INITIALIZING,那么就会从switch的最开始依次执行下来,把Fragment的生命周期onAttach–>onResume依次调用。
简要说明下上面的代码:

  • mHost是FragmentHostCallback抽象类的实例,它的实现类是Activity的HostCallbacks
  • mParent为null
  • mHost.getContext()获取的context就是宿主Activity实例
  • Fragment中创建的View会自动通过container.addView(f.mView)添加到父控件中

很多Fragment的生命周期是通过Fragment的performXxx()方法去调用的,比如:

    void performCreate(Bundle savedInstanceState) {        ......        onCreate(savedInstanceState);        ......    }    View performCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState) {        ......        return onCreateView(inflater, container, savedInstanceState);    }    void performActivityCreated(Bundle savedInstanceState) {        ......        onActivityCreated(savedInstanceState);        ......    }    void performStart() {        ......        onStart();        ......    }    void performResume() {        ......        onResume();        ......    }

Fragment状态的降级操作

有些童鞋们可能会有疑问,上面只分析到了onAttach->onResume生命周期的回调,那onPause、onDestroy等方法又是什么时候执行的呢?我们再看下刚才的代码

    if (f.mState < newState) {        ......    } else if (f.mState > newState) {        //state降级处理        ......    }

答案就是在else if分支里面,比如当Acivity锁屏的时候,就Activity生命周期会自动回调onPause,从而触发dispatchPause,在里面调用moveToState(Fragment.STARTED, false);
由于Fragment当前的状态是RESUMED状态,大于newState,所以就会走else if的分支,触发相应的生命周期方法。else if分支的逻辑和state升级的差不多,这里就再进行分析了

生命周期

这里写图片描述
最后,放张官网上公布的Fragment生命周期图,通过代码分析,我们发现代码的中生命周期的调用顺序和图中确实是一致的

总结

本文大致地从源码的角度分析了Fragment创建、生命周期回调的过程,如果读者对Fragment的removereplacehidedetachattach等操作有兴趣的话,可以自行分析,核心代码主要在BackStackRecord类的run方法以及FragmentManagerImpl的moveToState方法中。

1 0