Fragment 生命周期怎么来的?

前言

Fragment对于 Android 开发者来说一点都不陌生,因为几乎任何一款 app 都大量使用 Fragment,所以 Fragment 的生命周期相信对于大家来说应该都非常清楚,但绝大部分人对于其生命周期都停留在表象,知道一个 Fragment 从创建到运行再到销毁所要经过的过程,但却不知道内部如何实现。也许有人会这样说,给你一辆摩托车,你只要会骑就行,不需要拆开来看它内部的组成结构;对于这样的问题,我只想说,编程不仅学开车,还要学会造车,并且通过了解实现原理,可以让我们更加清晰的理解 Fragment的生命周期,往往我们通过理解来掌握的东西,是不易忘记的。

Fragment 生命周期流程图

好了,来看下面流程图来回顾一下 Fragment 的生命周期

分析

要分析 Fragment 的生命周期,离不开这四个类

FragmentActivity.java
FragmentManager.java
Fragment.java
BackStackRecord.java

启动 app 首先启动的是FragmentActivity,我们就从它开始看起,在 onCreate()方法中

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //Fragment管理类绑定 Activity
        mFragments.attachActivity(this, mContainer, null);
        // Old versions of the platform didn‘t do this!
        if (getLayoutInflater().getFactory() == null) {
            getLayoutInflater().setFactory(this);
        }

        super.onCreate(savedInstanceState);

        NonConfigurationInstances nc = (NonConfigurationInstances)
                getLastNonConfigurationInstance();
        if (nc != null) {
            mAllLoaderManagers = nc.loaders;
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);

            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
        }
        mFragments.dispatchCreate();
    }

这里的mFragments就是FragmentManager,onCreate 中主要做了两件事,一、把FragmentManager和 Activity绑定,二、 向 Fragment分发 OnCreate 方法mFragments.dispatchCreate();看到这里,不知道大家有没有疑问,这里就会执行 Fragment 的onAttach 和 onCreate 方法吗?答案显然是错误的,因为我们都知道我们在执行 add + commit的时候才会执行,那么这里的 attach 和 onCreate 做了什么事?进去看看

    public void attachActivity(FragmentActivity activity,
            FragmentContainer container, Fragment parent) {
        if (mActivity != null) throw new IllegalStateException("Already attached");
        mActivity = activity;
        mContainer = container;
        mParent = parent;
    }

以上代码,只是对变量的赋值,所以不会触发 Fragment 中的方法。

    public void dispatchCreate() {
        mStateSaved = false;
        moveToState(Fragment.CREATED, false);
    }

貌似触发了 Fragment 中的 onCreate方法,继续看看;

    void moveToState(int newState, int transit, int transitStyle, boolean always) {
        //...省略部分代码
        mCurState = newState;
        if (mActive != null) {
            boolean loadersRunning = false;
            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 (mActive != null),因为我们目前还没有地方初始化它,所以这里显然不成立,所以 dispatchCreate 方法也没有触发Fragment 中的任何方法,但是这里有一个需要注意

mCurState = newState;

也就是说当前状态变成了 Fragment.CREATED

FragmentActivity 中的其他方法如 onStart、onResume 都跟 onCreate 方法一样,都没有触发 Fragment 中的方法,

但mCurState 确发生了改变,变成了最后一个状态的值—> Fragment.RESUMED;

此时 Activity 已经启动了, FragmentManager中的mCurState也已经是Fragment.RESUMED,我们都知道,当我们通过FragmentManager.beginTransaction().add().commit()这时才是正在启动一个 Fragment,通过跟踪代码,commit最终调用的代码如下

    public void run() {
      //....省略很多代码
        while (op != null) {
            switch (op.cmd) {
                case OP_ADD: {
                    //add 会走这里
                    Fragment f = op.fragment;
                    f.mNextAnim = enterAnim;
                    mManager.addFragment(f, false);
                } break;
                case OP_REPLACE: {
                   //...省略
                } break;
                case OP_REMOVE: {
                    //...省略
                } break;
                case OP_HIDE: {
                   //...省略
                } break;
                case OP_SHOW: {
                   //...省略
                } break;
                case OP_DETACH: {
                   //...省略
                } break;
                case OP_ATTACH: {
                   //...省略
                } break;
                default: {
                 //...省略
                }
            }

            op = op.next;
        }
        //最后会去改变状态,这里就是整个生命周期执行的关键代码
        mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);

        if (mAddToBackStack) {
            mManager.addBackStackState(this);
        }
    }

上面代码很长,省略了部分代码,仅显示关键代码,当我们在 add 和 commit 之后,Fragment 会执行mManager.addFragment(f, false);这个方法

        if (mAvailIndices == null || mAvailIndices.size() <= 0) {
            if (mActive == null) {
                mActive = new ArrayList<Fragment>();
            }
            f.setIndex(mActive.size(), mParent);
            mActive.add(f);

        } else {
            //...省略
        }

我们在前面就已经讲过了这个if (mActive == null) ,它是在这里初始化的,所以当我们再次执行

moveToState(int newState, int transit, int transitStyle, boolean always)

的时候,这里是可以通过的,在 commit 之后就有这样一段代码

//最后会去改变状态,这里就是整个生命周期执行的关键代码
mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);

还记得mCurState的状态是什么吗?没错,就是我们前面分析的

mCurState = Fragment.RESUMED;

接下来就来看看 他是怎么moveToState

    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) {
    //...省略
        if (f.mState < newState) {
        //...省略
            }
            switch (f.mState) {
                case Fragment.INITIALIZING:
                //...省略
                    f.mCalled = false;
                    f.onAttach(mActivity);
                //...省略
                    if (f.mParentFragment == null) {
                        mActivity.onAttachFragment(f);
                    }

                    if (!f.mRetaining) {
                        f.performCreate(f.mSavedFragmentState);
                    }
                    f.mRetaining = false;
    //...省略
                    }
                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) {
                                container = (ViewGroup)mContainer.findViewById(f.mContainerId);
                                if (container == null && !f.mRestored) {
                                    throwException(new IllegalArgumentException(
                                            "No view found for id 0x"
                                            + Integer.toHexString(f.mContainerId) + " ("
                                            + f.getResources().getResourceName(f.mContainerId)
                                            + ") 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;
                                f.mView = NoSaveStateFrameLayout.wrap(f.mView);
                                if (container != null) {
                                    Animation anim = loadAnimation(f, transit, true,
                                            transitionStyle);
                                    if (anim != null) {
                                        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;
                    }
                case Fragment.ACTIVITY_CREATED:
                case Fragment.STOPPED:
                    if (newState > Fragment.STOPPED) {
                        if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
                        f.performStart();
                    }
                case Fragment.STARTED:
                    if (newState > Fragment.STARTED) {
                        if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                        f.mResumed = true;
                        f.performResume();
                        f.mSavedFragmentState = null;
                        f.mSavedViewState = null;
                    }
            }
        } else if (f.mState > newState) {
            switch (f.mState) {
                case Fragment.RESUMED:
                    if (newState < Fragment.RESUMED) {
                        if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
                        f.performPause();
                        f.mResumed = false;
                    }
                case Fragment.STARTED:
                    if (newState < Fragment.STARTED) {
                        if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
                        f.performStop();
                    }
                case Fragment.STOPPED:
                    if (newState < Fragment.STOPPED) {
                        if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f);
                        f.performReallyStop();
                    }
                case Fragment.ACTIVITY_CREATED:
                    if (newState < Fragment.ACTIVITY_CREATED) {
                        if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
                        if (f.mView != null) {
                            // Need to save the current view state if not
                            // done already.
                            if (!mActivity.isFinishing() && f.mSavedViewState == null) {
                                saveFragmentViewState(f);
                            }
                        }
                        f.performDestroyView();
                        if (f.mView != null && f.mContainer != null) {
                            Animation anim = null;
                            if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
                                anim = loadAnimation(f, transit, false,
                                        transitionStyle);
                            }
                            if (anim != null) {
                                final Fragment fragment = f;
                                f.mAnimatingAway = f.mView;
                                f.mStateAfterAnimating = newState;
                                anim.setAnimationListener(new AnimationListener() {
                                    @Override
                                    public void onAnimationEnd(Animation animation) {
                                        if (fragment.mAnimatingAway != null) {
                                            fragment.mAnimatingAway = null;
                                            moveToState(fragment, fragment.mStateAfterAnimating,
                                                    0, 0, false);
                                        }
                                    }
                                    @Override
                                    public void onAnimationRepeat(Animation animation) {
                                    }
                                    @Override
                                    public void onAnimationStart(Animation animation) {
                                    }
                                });
                                f.mView.startAnimation(anim);
                            }
                            f.mContainer.removeView(f.mView);
                        }
                        f.mContainer = null;
                        f.mView = null;
                        f.mInnerView = null;
                    }
                case Fragment.CREATED:
                    if (newState < Fragment.CREATED) {
                        if (mDestroyed) {
                            if (f.mAnimatingAway != null) {
                                // The fragment‘s containing activity is
                                // being destroyed, but this fragment is
                                // currently animating away.  Stop the
                                // animation right now -- it is not needed,
                                // and we can‘t wait any more on destroying
                                // the fragment.
                                View v = f.mAnimatingAway;
                                f.mAnimatingAway = null;
                                v.clearAnimation();
                            }
                        }
                        if (f.mAnimatingAway != null) {
                            // We are waiting for the fragment‘s view to finish
                            // animating away.  Just make a note of the state
                            // the fragment now should move to once the animation
                            // is done.
                            f.mStateAfterAnimating = newState;
                            newState = Fragment.CREATED;
                        } else {
                            if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
                            if (!f.mRetaining) {
                                f.performDestroy();
                            }

                            f.mCalled = false;
                            f.onDetach();
                            if (!f.mCalled) {
                                throw new SuperNotCalledException("Fragment " + f
                                        + " did not call through to super.onDetach()");
                            }
                            if (!keepActive) {
                                if (!f.mRetaining) {
                                    makeInactive(f);
                                } else {
                                    f.mActivity = null;
                                    f.mParentFragment = null;
                                    f.mFragmentManager = null;
                                    f.mChildFragmentManager = null;
                                }
                            }
                        }
                    }
            }
        }

        f.mState = newState;
    }

代码很多,也比较乱,这里我来简单分析一下,首先的知道这几种状态值的大小

    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.

现在是f.mState = Fragment.INITIALIZING,newState = RESUMED;

所以if (f.mState < newState)成立,特别注意在上面的代码中每一个 case 语句后面都没有 break 关键字,

所以简化以后的代码是:

switch (f.mState) {
   case Fragment.INITIALIZING:
       f.onAttach(mActivity);
        if (f.mParentFragment == null) {
             mActivity.onAttachFragment(f);
        }
        f (!f.mRetaining) {
            f.performCreate(f.mSavedFragmentState);
        }

   case Fragment.CREATED:
       f.performCreateView(...)
       f.onViewCreated(...)
       f.performActivityCreated(...);
       f.restoreViewState(...)
   case Fragment.ACTIVITY_CREATED:
   case Fragment.STOPPED:
       f.performStart();
   case Fragment.STARTED:
       f.performResume();

以上就是 Fragment 启动的全过程。看完启动,再来看看 Fragment 销毁的过程执行 remove().commit()之后会执行如下代码

 case OP_REMOVE: {
    Fragment f = op.fragment;
    f.mNextAnim = exitAnim;
    mManager.removeFragment(f, transition, transitionStyle);
} break;
    public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
        if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
        final boolean inactive = !fragment.isInBackStack();
        if (!fragment.mDetached || inactive) {
            if (mAdded != null) {
                mAdded.remove(fragment);
            }
            if (fragment.mHasMenu && fragment.mMenuVisible) {
                mNeedMenuInvalidate = true;
            }
            fragment.mAdded = false;
            fragment.mRemoving = true;
            moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
                    transition, transitionStyle, false);
        }
    }

可以看到最后一句,就是改变状态的调用,并且把newState 变为

Fragment.INITIALIZING或者Fragment.CREATED,如果当前 Fragment 在前台台运行,则为Fragment.INITIALIZING,我们假设当前值为Fragment.INITIALIZING,也就是当前运行的 Fragment 为我们所要移除的 Fragment;

因为if (f.mState < newState)不成立了,所以将会执行以下代码

else if (f.mState > newState) {
    switch (f.mState) {
    case Fragment.RESUMED:
    f.performPause();
    case Fragment.STARTED:
    f.performStop();
    case Fragment.STOPPED:
    f.performReallyStop();
    case Fragment.ACTIVITY_CREATED:
    saveFragmentViewState(f);
    f.performDestroyView();
    case Fragment.CREATED:
    f.performDestroy();
    f.onDetach();

千万不要被Fragment.CREATED这样的命名给疑惑了,,虽然这里写的是Fragment.CREATED,但它执行的确实performDestroy()

总结:

仔细分析就会发现整个生命周期其实很简单,简单来讲,就是 addView 和 removeView 的过程,只是在其中加入了其他类似 Activity 的 onStart 等方法。最后大家可以结合源码再看一遍!

时间: 2024-10-07 05:40:14

Fragment 生命周期怎么来的?的相关文章

打入电话时Fragment生命周期

Activity初次加载: MainActivity--->onCreate Mfragment---->onAttach Mfragment---->onCreate Mfragment---->onCreateView Mfragment---->onActivityCreated MainActivity--->onStart Mfragment---->onStart MainActivity--->onResume Mfragment---->

fragment生命周期及优点

fragment生命周期切换到该FragmentonAttach—> onCreate-> onCreateView—> onActivityCreated-> onStart-> onResume切换到其他Fragment:onPause-> onStop-> onDestroyView切换回本身的Fragment:onCreateView-> onActivityCreated-> onStart-> onResume显示Fragment时(

Fragment生命周期及其使用

Fragment是随着Android 3.0推出时携带的一部分,若是在1.6版本中使用,必须引入相应的支持包.Fragment最大的优点是你可以根据不同设备的屏幕大小创建动态的UI.Fragment有以下几个特点. 每个Fragment是个独立的模块 与其所在的Activity紧密的联系在一起 多个Activity可以共用一个Activity 1.Fragment生命周期. 首先来看下Fragment的生命周期,Fragment的生命周期和他所在的Activity的生命周期紧密联系在一起.因此看

关于fragment生命周期的两张图片

图1,fragment的生命周期,图2,fragment生命周期对应activity的生命周期

Fragment生命周期(转)

Android在3.0中引入了fragments的概念,主要目的是用在大屏幕设备上--例如平板电脑上,支持更加动态和灵活的UI设计.平板电脑的屏幕要比手机的大得多,有更多的空间来放更多的UI组件,并且这些组件之间会产生更多的交互.Fragment允许这样的一种设计,而不需要你亲自来管理viewhierarchy的复杂变化. 通过将activity的布局分散到fragment中, 你可以在运行时修改activity的外观,并在由activity管理的back stack中保存那些变化. 例如, 一

Activity生命周期和Fragment生命周期

工作时间不短了,却没怎么总结过.一直想对android的学习做个记录,那从这儿起吧.从最基础的知识一点点开始.很多内容是从大神那里搜罗来的. 一.Fragment生命周期图 二.Activity与Fragment生命周期比较

Android Activity生命周期以及Fragment生命周期的区别与分析

Android Fragment生命周期图: Activity生命周期图: 对照图: Fragment生命周期分析: 1. 当一个fragment被创建的时候,它会经历以下状态. onAttach() onCreate() onCreateView() onActivityCreated() 2. 当这个fragment对用户可见的时候,它会经历以下状态. onStart() onResume() 3. 当这个fragment进入“后台模式”的时候,它会经历以下状态. onPause() onS

Fragment生命周期-基于实验的最新总结

现在很多应用的开发都是基于FragmentActivity中嵌套Fragment进行开发的,所以,如果我们能够清晰地知道他们的生命周期,那么会使我们的开发变的容易. 对于Activity的生命周期,我在之前的文章 Activity生命周期-基于实验的最新总结  中已经说的很详细了,因此本篇文章只是从实践角度来讲一下Fragment的生命周期以及Fragment与Activity生命周期的对应关系,像大多数介绍Fragment生命周期的文章一样,先上两张图: 好,言归正传 这里从实例的角度来说明一

三张图让你快速明白activity与fragment生命周期的异同点

第一张图:activity的生命周期 第二张图:fragment的生命周期 第三张图:activity与fragment生命周期对比 补充:如果你还是不明白,请翻译一下你不理解的对应单词. ---------------------------------------------------------------------------------------- 有什么问题,大家可以一起交流-- 更多精彩关于关注博主的微信订阅号:非常周末 微信搜索:非常周末 你可以扫描一下关注即可:

Fragment(四)Fragment生命周期分析(转)

Fragment(四)Fragment生命周期分析 转载请注明:http://blog.csdn.net/liaoqianchuan00/article/details/24271607   例子一 从Layout中加载Fragment:   假设我们有一个Activity的Layout中有两个Fragment: <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=