Android之Fragment源码级彻底解析上

来源:互联网 发布:大数据时代 四大挑战 编辑:程序博客网 时间:2024/06/08 10:00

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的生命周期进行详解






1 0