Android之Fragment源码级彻底解析上
阅读原文时间:2021年04月20日阅读:1

1 举栗子

下面的例子我使用了2个Fragment作为Activity的布局

ContentFragment的布局

ContentFragment#fragment_content
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
    android:background="#00cccc"
    android:id="@+id/content"
    android:layout_height="match_parent">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:textSize="40sp"
    android:textColor="#FFFFFF"
    android:text="CONTENT"/>
</RelativeLayout>

ContentFragment.java

public class ContentFragment extends Fragment{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root=inflater.inflate(R.layout.fragment_content,container,false);
        return root;
    }
}

MenuFragment的布局

MenuFragment#fragment_menu
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#cccc00"
    android:id="@+id/menu"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="40sp"
        android:textColor="#FFFFFF"
        android:text="MENU"/>
</RelativeLayout>

MenuFragment.java

public class MenuFragment extends Fragment{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root=inflater.inflate(R.layout.fragment_menu,container,false);
        return root;
    }
}

然后是ManiActivity的布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:orientation="vertical">
    <FrameLayout
        android:id="@+id/fragment"
        android:layout_width="match_parent"
        android:layout_height="350dp"/>
    <Button
        android:id="@+id/bnt_content"
        android:text="SWITCH_CONTENT"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:background="#00cccc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/bnt_menu"
        android:text="SWITCH_MENU"
        android:background="#cccc00"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

ManiActivity.java

public class MainActivity extends Activity implements View.OnClickListener {
    private Button jump;
    private FrameLayout frame;
    private ContentFragment mContentFragment;
    private Button mContent;
    private Button mMenu;
    private MenuFragment mMenuFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        initView();
        setDefaultFragment();
        Log.e("activity", "____onCreate" + "___" + savedInstanceState+"_________Main");
    }
    private void setDefaultFragment() {
        FragmentManager fm=getFragmentManager();
        FragmentTransaction transaction=fm.beginTransaction();
        mContentFragment=new ContentFragment();
        transaction.replace(R.id.fragment,mContentFragment);
        transaction.commit();
    }

    private void initView() {
        mContent = (Button) findViewById(R.id.bnt_content);
        mMenu = (Button) findViewById(R.id.bnt_menu);
        mContent.setOnClickListener(this);
        mMenu.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        FragmentManager fm=getFragmentManager();
        FragmentTransaction transaction=fm.beginTransaction();
        switch (v.getId()) {
            case R.id.bnt_content:
                if (mContentFragment!=null){
                    mContentFragment=new ContentFragment();
                }
                transaction.replace(R.id.fragment,mContentFragment);
                break;
            case R.id.bnt_menu:
                if (mMenuFragment==null){
                    mMenuFragment=new MenuFragment();
                }
                transaction.replace(R.id.fragment,mMenuFragment);
                break;
        }
        transaction.commit();
    }
}

点击两个按钮可以切换相应的Fragment

2 Fragment家族常用API详解

Fragment常用的三个类:
android.app.Fragment 主要用于定义Fragment
android.app.FragmentManager 主要用于在Activity中操作Fragment
android.app.FragmentTransaction 保证一些列Fragment操作的原子性

(1)Fragment

Fragment是Android3.0引入的API,相比Activity更轻量级、更灵活

他有两种使用方式

(1.1)静态生成

静态写在xml中,和其他控件无差别

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <fragment
        android:name="com.example.huyucheng.test.FirstFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <fragment
        android:name="com.example.huyucheng.test.SecondFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

(1.2)代码动态生成

FragmentManager fm=getFragmentManager();
        FragmentTransaction transaction=fm.beginTransaction();
        mFirstFragment=new FirstFragment();
        transaction.add(R.id.fragment,mFirstFragment);
        transaction.addToBackStack(null);
        transaction.commit();

(2)FragmentManager

获取FragmentManager的方式:
getFragmentManager() // v4中,getSupportFragmentManager
fragmentManager并不是全局唯一的,而是每个activity都有一个自己的FragmentManager,内部有自己的状态mCurState,对应外部activity的生命周期状态。它提供和activity中fragment交互的API

(3)FragmentTransaction

主要的操作都是FragmentTransaction的方法,FragmentTransaction封装了一系列对fragment的操作,并一次性执行这些操作
FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务

transaction .commit();//提交一个事务

transaction.add() //往Activity中添加一个Fragment
transaction.remove() //从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。

transaction.addToBackStack(null);//回退栈

transaction.replace()//使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
transaction.hide()//隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
transaction.show()//显示之前隐藏的Fragment
detach()//会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。
attach()//重建view视图,附加到UI上并显示。

上面涉及到Fragment回退栈,视图移除等概念,可能很多人不太理解,莫慌,等我慢慢分析

3 源码分析

我们就从这个最常见的用法开始分析

FragmentManager fm=getFragmentManager();
        FragmentTransaction transaction=fm.beginTransaction();
        mFirstFragment=new FirstFragment();
        transaction.replace(R.id.fragment,mFirstFragment);
        transaction.commit();

(1)Activity

先来看看getFragmentManager()能得到什么

public FragmentManager getFragmentManager() {
        return mFragments.getFragmentManager();
    }

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

(2)FragmentController 

public FragmentManager getFragmentManager() {
        return mHost.getFragmentManagerImpl();
    }

FragmentController 里面真正执行的是mHost(FragmentHostCallback),很明显,这是一个桥接模式
(3)FragmentHostCallback

FragmentManagerImpl getFragmentManagerImpl() {
        return mFragmentManager;
    }

    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();

从这里可以看出我们经常调用的getFragmentManager()方法获取的其实是FragmentManagerImpl ,所以重点在FragmentManagerImpl 中

(4)FragmentManagerImpl
再来看看FragmentTransaction transaction=fm.beginTransaction();

@Override
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

所以这里我们常用的FragmentTransaction是BackStackRecord类型,重点在BackStackRecord里面

(5) BackStackRecord(实现了Runnble,replace、add、remove等操作都在run中进行)

再来分析 transaction.replace(R.id.fragment,mFirstFragment);

public FragmentTransaction replace(int containerViewId, Fragment fragment) {
        return replace(containerViewId, fragment, null);
    }

public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
        ......
        doAddOp(containerViewId, fragment, tag, OP_REPLACE);
        return this;
    }

replace中只有doAddOp方法,我们常说replace执行了remove和add,接下来我们就来看看doAddOp是不是真的执行了remove和add

private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        fragment.mFragmentManager = mManager;
    ......
        //下面的代码让fragment容器的id(mContainerId)和mFragmentId都指向framelayout布局id
        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 op = new Op();
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);
    }

上面的containerViewId是我们例子中MainActivity存放fragment的framelayout布局id,mManager就是FragmentManagerImpl ,

很显然,doAddOp只是对Op操作类进行了赋值,并没有做其他操作,再来看看addOp

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++;
    }

addOp简单的把当前赋值后的op增加到双链表的尾部,很显然,这里维护了一个双链表。

op.prev = mTail;和mTail.next = op;让op插入了双链表尾部,mTail = op;让mTail指针指向了当前的op(当前fragment),这里的链表使用的是尾插法,每个新插进来的fragment都位于尾部。

这里Op是BackStackRecord的内部类,是一个双链表数据结构

static final class Op {
        Op next;
        Op prev;
        int cmd;
        Fragment fragment;
        int enterAnim;
        int exitAnim;
        int popEnterAnim;
        int popExitAnim;
        ArrayList<Fragment> removed;
    }

依然,这里也没有看到replace所谓的remove和add操作,我们的replace操作在哪里执行的呢?接下来只有 transaction.commit();了

public int commit() {
        return commitInternal(false);
    }

int commitInternal(boolean allowStateLoss) {
        ......
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

还是没干啥,看看mManager. enqueueAction

(5)FragmentManagerImpl 

public void enqueueAction(Runnable action, boolean allowStateLoss) {
       ......
        synchronized (this) {
            ......
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<Runnable>();
            }
            mPendingActions.add(action);
            if (mPendingActions.size() == 1) {
                mHost.getHandler().removeCallbacks(mExecCommit);
                mHost.getHandler().post(mExecCommit);
            }
        }
    }

mPendingActions是专门装载Runnable的集合,从名字就可以看出enqueueAction就是把Runnable (BackStackRecord)加入到了集合中,
然后执行了mExecCommit(Runnble)

Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    };

再来看看execPendingActions

public boolean execPendingActions() {
    ......
        while (true) {
            int numActions;

            synchronized (this) {

                numActions = mPendingActions.size();
                if (mTmpActions == null || mTmpActions.length < numActions) {
                    mTmpActions = new Runnable[numActions];
                }
                //mPendingActions中保存的Runnble转移到了Runnble数组mTmpActions中
                mPendingActions.toArray(mTmpActions);
                mPendingActions.clear();
                mHost.getHandler().removeCallbacks(mExecCommit);
            }
            //在这里执行了Op操作
            for (int i=0; i<numActions; i++) {
                mTmpActions[i].run();
                mTmpActions[i] = null;
            }
        ......
        return didSomething;
    }

可以看到最终在execPendingActions中的mTmpActions[i].run()(即BackStackRecord.run())执行了 transaction.replace操作,接下来是重中之重
(6) BackStackRecord

public void run() {
        ......

        Op op = mHead;
        while (op != null) {
            switch (op.cmd) {
                case OP_ADD: {
                    Fragment f = op.fragment;
                    f.mNextAnim = op.enterAnim;
                    mManager.addFragment(f, false);
                }
                break;
                case OP_REPLACE: {
                    //获取新fragment
                    Fragment f = op.fragment;
                    int containerId = f.mContainerId;
                     //mManager.mAdded集合存放FragmentManagerImpl中的fragment
                    if (mManager.mAdded != null) {
                        for (int i = 0; i < mManager.mAdded.size(); i++) {
                    //old是mAdded集合最前面的一个fragment
                            Fragment old = mManager.mAdded.get(i);
                            //frameLayout布局的id相同进进行操作
                            if (old.mContainerId == containerId) {
                //如果fragment已经存在
                                if (old == f) {
                                    op.fragment = f = null;
                                } else {
                                    if (op.removed == null) {
                                        op.removed = new ArrayList<Fragment>();
                                    }
                    //把old fragment放入删除集合中
                                    op.removed.add(old);
                                    old.mNextAnim = op.exitAnim;
                                    if (mAddToBackStack) {
                                        old.mBackStackNesting += 1;
                                        if (FragmentManagerImpl.DEBUG) {
                                            Log.v(TAG, "Bump nesting of "
                                                    + old + " to " + old.mBackStackNesting);
                                        }
                                    }
                    //删除old fragment
                                    mManager.removeFragment(old, mTransition, mTransitionStyle);
                                }
                            }
                        }
                    }
                    if (f != null) {
                        f.mNextAnim = op.enterAnim;
            //增加新fragment
                        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;

            }

            op = op.next;
        }

        mManager.moveToState(mManager.mCurState, mTransition,
                mTransitionStyle, true);

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

trasaction.replace对应上面的OP_REPLACE,具体操作就是操作先删除全部的 fragment,然后增加新的fragment,mManager.removeFragment和mManager.addFragment都是对mAdded集合进行增删操作,
上面还可以看到
transaction.add() 
transaction.remove() 
transaction.addToBackStack(null);
transaction.replace()
transaction.hide()
transaction.show()
detach()
attach()

一系列方法的所有操作,到这里我们的整个fragment流程跑完了,接下来我们还会重点分析run方法里面的操作

上面的run方法在对这一系列Op处理完后,调用了下面的方法:

mManager.moveToState(mManager.mCurState, mTransition, mTransitionStyle, true);

显然这个方法用于改变Fragment的状态,这个方法最终会将FragmentManager的状态赋值给fragment,另外这个方法会根据不同的state调用各种onAttach, Fragment.performXXX,进而调到用户自己override的fragment的各种生命周期方法,比如onCreate、onCreateView等等

流程:ActivityThread.performXXX执行Activity的生命周期,fragmentManager的dispatchXXX方法跟着也执行了,fragmentManager的dispatchXXX中的moveToState根据不同的state调用fragment的生命周期函数

上面的run方法最后还调用下面的方法

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

很显然就是判断fragment是否要加入回退栈,其中mAddToBackStack就是在我们熟悉的addToBackStack方法中置true的

public FragmentTransaction addToBackStack(String name) {
        if (!mAllowAddToBackStack) {
            throw new IllegalStateException(
                    "This FragmentTransaction is not allowed to be added to the back stack.");
        }
        mAddToBackStack = true;
        mName = name;
        return this;
    }

Fragment的所有可能状态:

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.

FragmentManager中有一堆public void dispatchxxx这样的方法用于改变Fragment的生命周期状态

(7)FragmentManager

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

    public void dispatchActivityCreated() {
        mStateSaved = false;
        moveToState(Fragment.ACTIVITY_CREATED, false);
    }

    public void dispatchStart() {
        mStateSaved = false;
        moveToState(Fragment.STARTED, false);
    }

    public void dispatchResume() {
        mStateSaved = false;
        moveToState(Fragment.RESUMED, false);
    }

    public void dispatchPause() {
        moveToState(Fragment.STARTED, false);
    }

    public void dispatchStop() {
        moveToState(Fragment.STOPPED, false);
    }

    public void dispatchDestroyView() {
        moveToState(Fragment.CREATED, false);
    }

    public void dispatchDestroy() {
        mDestroyed = true;
        execPendingActions();
        moveToState(Fragment.INITIALIZING, false);
        mHost = null;
        mContainer = null;
        mParent = null;
    }

这些方法正好是和activity的生命周期对应起来,也就是说这些方法是随着activity进入到不同的生命周期而被调用的,即mCurState的值是被这些方法触发设置的。比如activity进入到了Resume状态,那么FragmentManagerImpl.mCurState也就等于Fragment.RESUMED

4 Fragment操作专项解析

之前在网上看多很多人各种分析,但是很多是基于UI结果来分析操作方法的区别,总感觉分析的不够科学,下面是基于源码分析操作方法,一直深入到最底层

再来回顾下那些难以区分的方法

transaction.add() //往Activity中添加一个Fragment
transaction.remove() //从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。
transaction.addToBackStack(null);//回退栈
transaction.replace()//使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
transaction.hide()//隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
transaction.show()//显示之前隐藏的Fragment
transaction.detach//会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。
transaction.attach()//重建view视图,附加到UI上并显示。

接下来结合BackStackRecord中run方法的源码来看

(1)transaction.add()

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

mManager.addFragment主要就是将fragment加入到了集合中,并改变fragment状态

public void addFragment(Fragment fragment, boolean moveToStateNow) {
            ......
            mAdded.add(fragment);
            ......
            if (moveToStateNow) {
                moveToState(fragment);
            }
        }
    }

(2)transaction.remove()

case OP_REMOVE: {
       Fragment f = op.fragment;
       f.mNextAnim = op.exitAnim;
       mManager.removeFragment(f, mTransition, mTransitionStyle);
    }
     break;

mManager.removeFragment主要就是将fragment从集合中删除,以及改变fragment的状态

public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
            ......
            if (mAdded != null) {
                mAdded.remove(fragment);
            }
            ......
            moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
                    transition, transitionStyle, false);
        }
    }

(3)transaction.replace()

 case OP_REPLACE: {
                    Fragment f = op.fragment;
                    int containerId = f.mContainerId;
                    if (mManager.mAdded != null) {
                        for (int i = 0; i < mManager.mAdded.size(); i++) {
                            Fragment old = mManager.mAdded.get(i);
                       ......
                            mManager.removeFragment(old, mTransition, mTransitionStyle);
                ......
                        }
                    }
                    if (f != null) {
                        f.mNextAnim = op.enterAnim;
                        mManager.addFragment(f, false);
                    }
                }
                break;

这个上面已经分析了,移除所有老fragment,再把新的加进来

(4)transaction.hide()

case OP_HIDE: {
        Fragment f = op.fragment;
        f.mNextAnim = op.exitAnim;
        mManager.hideFragment(f, mTransition, mTransitionStyle);
      }

public void hideFragment(Fragment fragment, int transition, int transitionStyle) {
        if (DEBUG) Log.v(TAG, "hide: " + fragment);
        if (!fragment.mHidden) {
            fragment.mHidden = true;
            if (fragment.mView != null) {
                Animator anim = loadAnimator(fragment, transition, false,
                        transitionStyle);
                if (anim != null) {
                    anim.setTarget(fragment.mView);

                    final Fragment finalFragment = fragment;
                    anim.addListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            if (finalFragment.mView != null) {
                //改变fragment根View的visibility属性为Gone
                                finalFragment.mView.setVisibility(View.GONE);
                            }
                        }
                    });
                    anim.start();
                } else {
                    fragment.mView.setVisibility(View.GONE);
                }
            }
            ......
            fragment.onHiddenChanged(true);
        }
    }

transaction.hide()只是改变fragment根View的visibility为gone

(5)transaction.show()

case OP_SHOW: {
        Fragment f = op.fragment;
        f.mNextAnim = op.enterAnim;
        mManager.showFragment(f, mTransition, mTransitionStyle);
       }
      break;

public void showFragment(Fragment fragment, int transition, int transitionStyle) {
        if (fragment.mHidden) {
            fragment.mHidden = false;
            if (fragment.mView != null) {
                Animator anim = loadAnimator(fragment, transition, true,
                        transitionStyle);
                if (anim != null) {
                    anim.setTarget(fragment.mView);
                    setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
                    anim.start();
                }
                fragment.mView.setVisibility(View.VISIBLE);
            }
            fragment.onHiddenChanged(false);
        }
    }

transaction.show只是让fragment.hidden==true的fragment根View的visibility属性为VISIBLE

(6)transaction.attach()

case OP_ATTACH: {
        Fragment f = op.fragment;
        f.mNextAnim = op.enterAnim;
        mManager.attachFragment(f, mTransition, mTransitionStyle);
      }
       break;

public void attachFragment(Fragment fragment, int transition, int transitionStyle) {
        if (fragment.mDetached) {
            fragment.mDetached = false;
            if (!fragment.mAdded) {
                if (mAdded == null) {
                    mAdded = new ArrayList<Fragment>();
                }
                if (mAdded.contains(fragment)) {
                    throw new IllegalStateException("Fragment already added: " + fragment);
                }
                mAdded.add(fragment);
                fragment.mAdded = true;
                moveToState(fragment, mCurState, transition, transitionStyle, false);
            }
        }
    }

(7)transaction.detach()

case OP_DETACH: {
       Fragment f = op.fragment;
       f.mNextAnim = op.exitAnim;
       mManager.detachFragment(f, mTransition, mTransitionStyle);
   }
   break;



public void detachFragment(Fragment fragment, int transition, int transitionStyle) {
        if (!fragment.mDetached) {
            fragment.mDetached = true;
            if (fragment.mAdded) {
                // We are not already in back stack, so need to remove the fragment.
                if (mAdded != null) {
                    if (DEBUG) Log.v(TAG, "remove from detach: " + fragment);
                    mAdded.remove(fragment);
                }
                if (fragment.mHasMenu && fragment.mMenuVisible) {
                    mNeedMenuInvalidate = true;
                }
                fragment.mAdded = false;
                moveToState(fragment, Fragment.CREATED, transition, transitionStyle, false);
            }
        }
    }

detach的时候onPause、onStop、onDestroyView会被调用,onDestroy、onDetach不会被调用

(8)transaction.addToBackStack(null)

我们调用transaction.addToBackStack后实际让mAddToBackStack = true;然后run方法里面再执行 mManager.addBackStackState(this);

public FragmentTransaction addToBackStack(String name) {
        if (!mAllowAddToBackStack) {
            throw new IllegalStateException(
                    "This FragmentTransaction is not allowed to be added to the back stack.");
        }
        mAddToBackStack = true;
        mName = name;
        return this;
    }

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

void addBackStackState(BackStackRecord state) {
        if (mBackStack == null) {
            mBackStack = new ArrayList<BackStackRecord>();
        }
        mBackStack.add(state);
        reportBackStackChanged();
    }

5 总结

(1)在上面的过程中我们跑通了fragment常用API的整个流程

FragmentManager fm=getFragmentManager();
        FragmentTransaction transaction=fm.beginTransaction();
        mFirstFragment=new FirstFragment();
        transaction.add(R.id.fragment,mFirstFragment);
        transaction.addToBackStack(null);
        transaction.commit();

其中FragmentManager 的实现类FragmentManagerImpl 

FragmentTransaction 的实现类BackStackRecord,BackStackRecord的run方法包含了对fragment的所有操作

整个生命周期流程:ActivityThread.performXXX执行Activity的生命周期,fragmentManager的dispatchXXX方法跟着也执行了,fragmentManager的dispatchXXX中的moveToState根据不同的state调用fragment的生命周期函数

(2)show/hideFragment只是改变fragment根View的visibility,最多带上个动画效果,另外只有本身是hidden的fragment,调用show才起作用,否则没用的,fragment.onHiddenChanged会被触发;其次不会有生命周期callback触发,当然了这些操作的前提是已经被add了的fragment;

(3)addFragment的时候,不管加不加入回退栈都一样,经历的生命周期如下:onAttach、onCreate、onCreateView、onActivityCreate、onStart、onResume;

(4)removeFragment的时候,经历的生命周期如下:onPause、onStop、onDestroyView,如果不加回退栈还会继续走onDestroy、onDetach;remove的时候不仅从mAdded中移除fragment,也从mActive中移除了;

(5)attach/detachFragment的前提都是已经add了的fragment,其生命周期回调不受回退栈影响。attach的时候onCreateView、onActivityCreate、onStart、onResume会被调用;detach的时候onPause、onStop、onDestroyView会被调用,onDestroy、onDetach不会被调用;对应的fragment只是从mAdded中移除了

(6)remove、detachFragment的时候,当FragmentManagerImpl.makeInactive()被调用的话,fragment就变成了一个空壳,里面绝大部分字段都会被置空,注意只是系统内部自己管理的字段,假如你在自己的fragment子类中引入了新的字段,当你重用这些类的对象时要自己处理这种情况(即系统不会reset你自己造的字段)

void makeInactive(Fragment f) {
        ......
        f.initState();
    }
    void initState() {
        mIndex = -1;
        mWho = null;
        mAdded = false;
        mRemoving = false;
        mResumed = false;
        mFromLayout = false;
        mInLayout = false;
        mRestored = false;
        mBackStackNesting = 0;
        mFragmentManager = null;
        mChildFragmentManager = null;
        mHost = null;
        mFragmentId = 0;
        mContainerId = 0;
        mTag = null;
        mHidden = false;
        mDetached = false;
        mRetaining = false;
        mLoaderManager = null;
        mLoadersStarted = false;
        mCheckedForLoaderManager = false;
    }

这一篇章多次涉及到fragment的生命周期,下一篇篇章将对fragment的生命周期进行详解