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