注意:文章對Fragment源碼的分析基于support v4的Fragment包,版本號為25.3.1
Fragment相關類UML圖

support包中對負責管理Fragment生命是FragmentActivity,v7包的AppCompatActivity也是繼承于它。
FragmentActivity管理Fragment是通過它內(nèi)部mFragments的變量,mFragments類型為FragmentController.
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
FragmentActivity傳遞自身生命狀態(tài)、狀態(tài)保存、恢復都是通過調(diào)用mFragments相應的方法進行處理;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mFragments.attachHost(null /*parent*/);
super.onCreate(savedInstanceState);
//...
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
//...
mFragments.dispatchCreate();
}
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
而FragmentController本身只是簡單的將相應請求轉(zhuǎn)發(fā)給FragmentManagerImpl,只是起到了橋梁溝通作用。
FragmentActivity創(chuàng)建mFragments時傳遞了一個HostCallbacks內(nèi)部類實例,這個callback對象給Fragment提供了獲取Context,啟動Activity的能力。
Fragment
Fragment主要是由Attr、View、State構(gòu)成,
Attr:固有屬性,F(xiàn)ragment基本信息,基本不會隨生命周期變化。
Bundle mArguments; //構(gòu)造參數(shù)
boolean mFromLayout; //是否從layout文件中創(chuàng)建
String mTag;
...
View:Fragment管理View所依賴的相關成員變量。
// The parent container of the fragment after dynamically added to UI.
ViewGroup mContainer;
// The View generated for this fragment.
View mView;
// The real inner view that will save/restore state.
View mInnerView;
State:Fragment的狀態(tài),管理Fragment的顯示、生命周期。
int mState = INITIALIZING; //生命周期狀態(tài)
boolean mAdded; //是否被添加
boolean mRemoving; //是否被移除
boolean mHidden;// 是否被隱藏
boolean mDetached; //是否已經(jīng)分離
// mState取值如下
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.
Fragment的生命周期方法,onAttach, onCreate, onCreateView...都是在mState狀態(tài)變化中進行回調(diào)的。
Fragment的事務:FragmentTransaction、BackStackRecord
添加一個Fragment,我們一般使用如下代碼:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contaniner, fragment);
transaction.commit();
FragmentTransaction表示一個事務,提供了如add、remove、attach、detach、show、hide、replace等接口操控Fragment。它的具體實現(xiàn)類是BackStackRecord,它的接口實現(xiàn)如下:
@Override
public FragmentTransaction add(Fragment fragment, String tag) {
doAddOp(0, fragment, tag, OP_ADD);
return this;
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
...
Op op = new Op();
op.cmd = opcmd;
op.fragment = fragment;
addOp(op);
}
void addOp(Op op) {
mOps.add(op);
op.enterAnim = mEnterAnim;
op.exitAnim = mExitAnim;
op.popEnterAnim = mPopEnterAnim;
op.popExitAnim = mPopExitAnim;
}
@Override
public FragmentTransaction remove(Fragment fragment) {
Op op = new Op();
op.cmd = OP_REMOVE;
op.fragment = fragment;
addOp(op);
return this;
}
...
可以看到我們調(diào)用的add、remove等方法最后都是生成一個Op對象保存在mOps列表中,Op是Operator簡寫表示操作,Op的cmd屬性則區(qū)分操作的類型,cmd的值取如下幾種:
static final int OP_NULL = 0;
static final int OP_ADD = 1;
static final int OP_REPLACE = 2;
static final int OP_REMOVE = 3;
static final int OP_HIDE = 4;
static final int OP_SHOW = 5;
static final int OP_DETACH = 6;
static final int OP_ATTACH = 7;
上面操作完畢后,最后是commit事務了
@Override
public int commit() {
return commitInternal(false);
}
@Override
public int commitAllowingStateLoss() {
return commitInternal(true);
}
@Override
public void commitNow() {
...
// 直接開始執(zhí)行事務
mManager.execSingleAction(this, false);
}
@Override
public void commitNowAllowingStateLoss() {
...
// 直接開始執(zhí)行事務
mManager.execSingleAction(this, true);
}
int commitInternal(boolean allowStateLoss) {
...
// 事務入對象,等待下一個Handler回調(diào)執(zhí)行
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
*AllowingStateLoss表示是否允許狀態(tài)丟失,如果不允許但是當前Activity狀態(tài)已經(jīng)觸發(fā)保存了調(diào)用會拋出異常;commit、commitNow的區(qū)別則是提交事務等待下個主線程Handler回調(diào)執(zhí)行還是立即執(zhí)行,除了執(zhí)行時機不一樣外,兩者最后觸發(fā)的事務執(zhí)行邏輯是一樣的。
事務執(zhí)行邏輯依然在BackStackRecord中:
void executeOps() {
final int numOps = mOps.size();
for (int opNum = 0; opNum < numOps; opNum++) {
final Op op = mOps.get(opNum);
final Fragment f = op.fragment;
f.setNextTransition(mTransition, mTransitionStyle);
switch (op.cmd) {
case OP_ADD:
f.setNextAnim(op.enterAnim);
mManager.addFragment(f, false);
break;
case OP_REMOVE:
f.setNextAnim(op.exitAnim);
mManager.removeFragment(f);
break;
case OP_HIDE:
f.setNextAnim(op.exitAnim);
mManager.hideFragment(f);
break;
case OP_SHOW:
f.setNextAnim(op.enterAnim);
mManager.showFragment(f);
break;
case OP_DETACH:
f.setNextAnim(op.exitAnim);
mManager.detachFragment(f);
break;
case OP_ATTACH:
f.setNextAnim(op.enterAnim);
mManager.attachFragment(f);
break;
default:
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
}
if (!mAllowOptimization && op.cmd != OP_ADD) {
mManager.moveFragmentToExpectedState(f);
}
}
if (!mAllowOptimization) {
// Added fragments are added at the end to comply with prior behavior.
mManager.moveToState(mManager.mCurState, true);
}
}
執(zhí)行邏輯是遍歷所有添加的操作,執(zhí)行相應的FragmentManage方法,最后將Fragment的狀態(tài)移動的相應的狀態(tài)。
Fragment狀態(tài)變遷:moveToState
Fragment添加到FragmentMange中后,要將它移動到相應的狀態(tài),使Fragment正確的顯示、交互。
FragmentManage的成員變量mCurState存儲著當前Activity狀態(tài)對應的Fragment狀態(tài)值,它的取值范圍如同F(xiàn)ragment。Activity的狀態(tài)發(fā)生變化時都會觸發(fā)相應方法修改mCurState,并將所有的active 的Fragment移動到相應的狀態(tài)上。
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() {
// See saveAllState() for the explanation of this. We do this for
// all platform versions, to keep our behavior more consistent between
// them.
mStateSaved = true;
moveToState(Fragment.STOPPED, false);
}
public void dispatchReallyStop() {
moveToState(Fragment.ACTIVITY_CREATED, false);
}
public void dispatchDestroyView() {
moveToState(Fragment.CREATED, false);
}
public void dispatchDestroy() {
mDestroyed = true;
execPendingActions();
moveToState(Fragment.INITIALIZING, false);
mHost = null;
mContainer = null;
mParent = null;
}
FragmentManage的moveToState方法就負責了將自己管理的所有Fragment的狀態(tài)移動到對應的狀態(tài)上,當mCurState變化,或者Fragment操作觸發(fā)都會調(diào)用該方法。
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// Fragments that are not currently added will sit in the onCreate() state.
...
if (f.mState < newState) {
// For fragments that are created from a layout, when restoring from
// state we don't want to allow them to be created until they are
// being reloaded from the layout.
...
switch (f.mState) {
case Fragment.INITIALIZING:
...
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
...
}
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.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();
}
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) {
...
}
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
...
}
}
}
...
}
fragment的state取值,為前面提到的七中狀態(tài),其中最低值是INITIALIZING狀態(tài),代表fragment剛創(chuàng)建,還未被add, 最高狀態(tài)值是RESUMED,代表fragment處于前臺。 所以moveToState內(nèi)部分兩條線,狀態(tài)躍升,和狀態(tài)降低,里面各有一個switch判斷,注意到switch里每個case都沒有break,這意味著,狀態(tài)可以持續(xù)變遷,比如從INITIALIZING,一直躍升到RESUMED,將每個case都走一遍,每次case語句內(nèi),都會改變state的值。

Fragment狀態(tài)保存、恢復
主要實現(xiàn)代碼是FragmentManageImpl的saveAllState()和restoreAllState()方法。
FragmentActivity的onSaveInstance()方法中會間接調(diào)用FragmentManageImpl的saveAllState()方法,而onCreate(Bundle)中會間接調(diào)用restoreAllState()。在Fragment的onCreate(Bundle)等初始化生命方法中會傳入保存狀態(tài)的Bundle,以供開發(fā)者恢復存儲的數(shù)據(jù)。而Fragment中view的狀態(tài)的恢復則是在回調(diào)了onCreateView()后得到開發(fā)者返回的view,手動觸發(fā)view狀態(tài)的恢復:
// FragmentManageImpl.class
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
...
if(f.mState < newState) { // 狀態(tài)升
...
switch(f.mState) {
...
case Fragment.CREATED:
...
f.mView = f.performCreateView(f.performGetLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
...
f.performActivityCreated(f.mSavedFragmentState);
...
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
...
}
...
}
// Fragment.class
final void restoreViewState(Bundle savedInstanceState) {
if (mSavedViewState != null) {
mInnerView.restoreHierarchyState(mSavedViewState);
mSavedViewState = null;
}
mCalled = false;
onViewStateRestored(savedInstanceState);
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onViewStateRestored()");
}
}
Fragment常見錯誤:
可以參考:http://www.itdecent.cn/p/d9143a92ad94
getActivity空指針錯誤
狀態(tài)沒保存、值丟失
Can not perform this action after onSaveInstanceState異常
Fragment類必須提供無參構(gòu)造方法
Fragment重疊顯示異常
其他
Fragment中還有回退棧、動畫、Android5.0中的共享元素及Activity動畫、Fragment.retainInstance屬性、LoaderManager、ChildFragmentManage等知識點這里先不討論了。