Fragment啟動過程,從getFragmentManager開始
概述
時至今日,Fragment已經成為Android開發中應用最廣泛的方案了,幾乎每一個APP都離不開它的影子。為了更深入的理解其中原理,我們從Fragment中原始碼開始分析。這裡我們選擇V4包中的Fragment來進行分析。
為了在低版本中使用Fragment需要用到V4相容包,我們首先需要繼承V4包中FragmentActivity,它提供了操作Fragment的一些方法。如果有對V4不太瞭解的同學,網上關於V4的說明非常豐富,可以自行查閱。
FragmentActivity初始化
如上在使用Fragment之前,我們首先繼承FragmentActivity類。我們知道當一個Activity開啟後,一般都會在onCreate方法中進行一些初始化操作。我們可以先看onCreate方法。
FragmentActivity#onCreate
.....
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
.....
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//step 1:
mFragments.attachHost(null /*parent*/);
super.onCreate(savedInstanceState);
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
mFragments.restoreLoaderNonConfig(nc.loaders);
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
// Check if there are any pending onActivityResult calls to descendent Fragments.
if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) {
mNextCandidateRequestIndex =
savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG);
int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG);
String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG);
if (requestCodes == null || fragmentWhos == null ||
requestCodes.length != fragmentWhos.length) {
Log.w(TAG, "Invalid requestCode mapping in savedInstanceState.");
} else {
mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length);
for (int i = 0; i < requestCodes.length; i++) {
mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
}
}
}
}
if (mPendingFragmentActivityResults == null) {
mPendingFragmentActivityResults = new SparseArrayCompat<>();
mNextCandidateRequestIndex = 0;
}
//step 2:
mFragments.dispatchCreate();
}
如上,我們知道mFragments是FragmentController類。該引用在FragmentActivity被載入時,會被初始化。我們來看對
FragmentController的介紹:
/**
* Provides integration points with a {@link FragmentManager} for a fragment host.
* <p>
* It is the responsibility of the host to take care of the Fragment's lifecycle.
* The methods provided by {@link FragmentController} are for that purpose.
*/
FragmentController提供了方法來負責管理Fragment的生命週期,分發給fragment host中的FragmentManager。繼續來看下FragmentController內部的程式碼:
public class FragmentController {
private final FragmentHostCallback<?> mHost;
/**
* Returns a {@link FragmentController}.
*/
public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback<?> callbacks) {
mHost = callbacks;
}
/**
* Returns a {@link FragmentManager} for this controller.
*/
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
.....
public void attachHost(Fragment parent) {
mHost.mFragmentManager.attachController(
mHost, mHost /*container*/, parent);
}
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
}
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
.....
}
FragmentController是個單例的實現,內部持有一個FragmentHostCallback引用,外部在呼叫方法createController時,傳入FragmentHostCallback引數(這裡傳遞的是HostCallbacks物件),來建立一個FragmentController物件。
繼續檢視下FragmentHostCallback類:
public abstract class FragmentHostCallback<E> extends FragmentContainer {
private final Activity mActivity;
final Context mContext;
private final Handler mHandler;
final int mWindowAnimations;
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
/** The loader managers for individual fragments [i.e. Fragment#getLoaderManager()] */
private SimpleArrayMap<String, LoaderManager> mAllLoaderManagers;
/** Whether or not fragment loaders should retain their state */
private boolean mRetainLoaders;
/** The loader manger for the fragment host [i.e. Activity#getLoaderManager()] */
private LoaderManagerImpl mLoaderManager;
private boolean mCheckedForLoaderManager;
/** Whether or not the fragment host loader manager was started */
private boolean mLoadersStarted;
public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
this(context instanceof Activity ? (Activity) context : null, context, handler,windowAnimations);
}
FragmentHostCallback(FragmentActivity activity) {
this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
}
FragmentHostCallback(Activity activity, Context context, Handler handler,
int windowAnimations) {
mActivity = activity;
mContext = context;
mHandler = handler;
mWindowAnimations = windowAnimations;
}
......
}
我們來分析該類中持有的引用:
mActivity:當前Fragment中的宿主Activity
mContext:當前Fragment中的宿主Activity
mHandler:當前Fragment中的宿主Activity中的handler屬性
以上都是通過新建FragmentHostCallback物件時,通過引數傳遞而來。
而我們看到該類中還例項化了一個FragmentManagerImpl物件,該物件是FragmentManager具體實現類,由它來管理Fragment的生命週期。稍後我們將詳細分析這個類。
現在我們回到前面FragmentActivity中,再梳理一下流程。首先在載入FragmentActivity時,生成了FragmentController物件,這裡以HostCallbacks作為FragmentHostCallback實現類,作為引數傳入。到這一步就完成了FragmentHostCallback內部屬性的初始化過程。
接著我們回到FragmentActivity的onCreate方法:
step 1: 執行mFragments.attachHost(null);
FragmentController#attachHost
public void attachHost(Fragment parent) {
mHost.mFragmentManager.attachController(mHost, mHost /*container*/, parent);
}
這裡的mHost,我們知道是HostCallbacks例項化物件。mFragmentManager的具體實現物件是FragmentManagerImpl,所以這裡直接呼叫FragmentManagerImpl的方法:
FragmentManagerImpl#attachController
public void attachController(FragmentHostCallback host,
FragmentContainer container, Fragment parent) {
if (mHost != null) throw new IllegalStateException("Already attached");
mHost = host;
mContainer = container;
mParent = parent;
}
這裡方法中傳遞的引數分別是:
host:HostCallbacks物件
container:HostCallbacks物件
parent:null
從這裡可以看出在執行mFragments.attachHost(null)時,就是將物件中的引數初始化。而這些物件之間的關係,如下:
step 2: 執行mFragments.dispatchCreate();
FragmentController#dispatchCreate
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
同樣的執行的是FragmentManagerImpl中的方法:
FragmentManagerImpl#dispatchCreate
public void dispatchCreate() {
mStateSaved = false;
mExecutingActions = true;
moveToState(Fragment.CREATED, false);
mExecutingActions = false;
}
裡面執行了一個重要的方法:moveToState,這個方法用來更改fragment manager中的當前狀態。這裡傳入的引數值為:
newState = Fragment.CREATED
always = false
FragmentManagerImpl#moveToState
void moveToState(int newState, boolean always) {
//判斷宿主不能為空
if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No activity");
}
// 與當前狀態相同時,不處理
if (!always && newState == mCurState) {
return;
}
// 儲存當前狀態
mCurState = newState;
if (mActive != null) {
boolean loadersRunning = false;
// Must add them in the proper order. mActive fragments may be out of order
if (mAdded != null) {
final int numAdded = mAdded.size();
for (int i = 0; i < numAdded; i++) {
Fragment f = mAdded.get(i);
moveFragmentToExpectedState(f);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
// Now iterate through all active fragments. These will include those that are removed
// and detached.
final int numActive = mActive.size();
for (int i = 0; i < numActive; i++) {
Fragment f = mActive.get(i);
if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
moveFragmentToExpectedState(f);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
if (!loadersRunning) {
startPendingDeferredFragments();
}
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onSupportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
}
方法中儲存當前狀態為:Fragment.CREATED,初次載入時 mActive 屬性為null,裡面的程式碼將不會執行。
在這裡補充說明一下,前面我們說過FragmentController提供了方法來負責管理Fragment的生命週期,用來將Activity的生命週期分發給fragment host中的FragmentManager,從而方便對Fragment的生命週期的管理。
我們可以看下FragmentActivity中的生命週期方法中執行的引數:
FragmentActivity
@Override
protected void onStart() {
super.onStart();
.....
mFragments.dispatchStart();
.....
}
@Override
protected void onPostResume() {
super.onPostResume();
mHandler.removeMessages(MSG_RESUME_PENDING);
onResumeFragments();
mFragments.execPendingActions();
}
protected void onResumeFragments() {
mFragments.dispatchResume();
}
@Override
protected void onPause() {
super.onPause();
mResumed = false;
if (mHandler.hasMessages(MSG_RESUME_PENDING)) {
mHandler.removeMessages(MSG_RESUME_PENDING);
onResumeFragments();
}
mFragments.dispatchPause();
}
@Override
protected void onStop() {
super.onStop();
mStopped = true;
mHandler.sendEmptyMessage(MSG_REALLY_STOPPED);
mFragments.dispatchStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
doReallyStop(false);
mFragments.dispatchDestroy();
mFragments.doLoaderDestroy();
}
可以看出隨著FragmentActivity中生命週期的變化,Fragment生命週期做出相應的改變。
我們再看看FragmentManager中,對應Fragment的生命週期的操作。
public void dispatchCreate() {
mStateSaved = false;
mExecutingActions = true;
moveToState(Fragment.CREATED, false);
mExecutingActions = false;
}
public void dispatchActivityCreated() {
mStateSaved = false;
mExecutingActions = true;
moveToState(Fragment.ACTIVITY_CREATED, false);
mExecutingActions = false;
}
public void dispatchStart() {
mStateSaved = false;
mExecutingActions = true;
moveToState(Fragment.STARTED, false);
mExecutingActions = false;
}
public void dispatchResume() {
mStateSaved = false;
mExecutingActions = true;
moveToState(Fragment.RESUMED, false);
mExecutingActions = false;
}
public void dispatchPause() {
mExecutingActions = true;
moveToState(Fragment.STARTED, false);
mExecutingActions = 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;
mExecutingActions = true;
moveToState(Fragment.STOPPED, false);
mExecutingActions = false;
}
public void dispatchReallyStop() {
mExecutingActions = true;
moveToState(Fragment.ACTIVITY_CREATED, false);
mExecutingActions = false;
}
public void dispatchDestroyView() {
mExecutingActions = true;
moveToState(Fragment.CREATED, false);
mExecutingActions = false;
}
public void dispatchDestroy() {
mDestroyed = true;
execPendingActions();
mExecutingActions = true;
moveToState(Fragment.INITIALIZING, false);
mExecutingActions = false;
mHost = null;
mContainer = null;
mParent = null;
}
上面完成了關鍵物件引數的初始化後,下面我們就來呼叫了。如果使用程式碼動態載入Fragment的話,我們一般執行下面程式碼:
Fragment fragment = new Fragment();
.....
//step 1
FragmentManager manager = getSupportFragmentManager();
//step 2
FragmentTransaction transaction = manager.beginTransaction();
//step 3
transaction.add(R.id.fragment_container, fragment);
//step 4
transaction.commit();
step 1:
FragmentActivity#getSupportFragmentManager
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
裡面其實是執行:
FragmentController#getSupportFragmentManager
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
這裡我們知道獲取之前初始化的FragmentManagerImpl的物件例項。
step 2:
執行的是FragmentManagerImpl中方法:
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
這裡直接建立一個BackStackRecord例項物件,傳入的引數是之前例項化的FragmentManagerImpl物件,此物件現在複製給BackStackRecord類內部的mManager屬性。
由此可以BackStackRecord是FragmentTransaction的具體實現類。
step 3:
.....
static final class Op {
int cmd;
Fragment fragment;
int enterAnim;
int exitAnim;
int popEnterAnim;
int popExitAnim;
}
ArrayList<Op> mOps = new ArrayList<>();
......
@Override
public FragmentTransaction add(int containerViewId, Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
final Class fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
// 判斷fragmentClass 是否符合要求
if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
|| (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers))) {
throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
+ " must be a public static class to be properly recreated from"
+ " instance state.");
}
// 將mManager屬性賦值給fragment中的 mFragmentManager
fragment.mFragmentManager = mManager;
// 如果tag不為空並且與fagment中當前mTag不相等,則賦值
if (tag != null) {
if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
throw new IllegalStateException("Can't change tag of fragment "
+ fragment + ": was " + fragment.mTag
+ " now " + tag);
}
fragment.mTag = tag;
}
// containerViewId 不為0 且與 fragment中的mFragmentId不相等事,則賦值。
if (containerViewId != 0) {
if (containerViewId == View.NO_ID) {
throw new IllegalArgumentException("Can't add fragment "
+ fragment + " with tag " + tag + " to container view with no id");
}
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 = new Op();
op.cmd = opcmd;
op.fragment = fragment;
addOp(op); //將fragment加入ArrayList集合中。
}
step 4:
BackStackRecord#commit
@Override
public int commit() {
return commitInternal(false);
}
BackStackRecord#commitInternal
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", null, pw, null);
pw.close();
}
// 賦值,不能重複提交
mCommitted = true;
//判斷是否加入返回棧
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
FragmentManagerImpl#enqueueAction
呼叫方法commit時,傳入為false;
呼叫方法commitAllowingStateLoss時,傳入為true;
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<>();
}
mPendingActions.add(action);
scheduleCommit();
}
}
使用commit方法提交時,會執行checkStateLoss方法來判斷當前狀態是否儲存,我們來看下
FragmentManagerImpl#checkStateLoss
private void checkStateLoss() {
//狀態為true時,丟擲異常
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
// 不為空時,丟擲異常
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}
主要來分析mStateSaved為true的情況:
1.執行saveAllState方法時,如果版本為HONEYCOMB(Android 3.0) 以上時,都會將mStateSaved設定為true。而這個方法在Activity中的onSaveInstanceState執行。
2.在執行dispatchStop時,mStateSaved狀態也會被設定為true。而這個方法發生在Activity中的onStop回撥。
上述兩中情形下,不能執行commit的操作。
完成saveAllState狀態判斷之後,再來執行方法scheduleCommit:
FragmentManagerImpl#scheduleCommit
private void scheduleCommit() {
synchronized (this) {
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
FragmentManagerImpl#execPendingActions
/**
* Only call from main thread!
*/
public boolean execPendingActions() {
//執行操作前的準備階段
ensureExecReady(true);
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
doPendingDeferredStart();
return didSomething;
}
FragmentManagerImpl#ensureExecReady
private void ensureExecReady(boolean allowStateLoss) {
if (mExecutingActions) {
throw new IllegalStateException("FragmentManager is already executing transactions");
}
if (Looper.myLooper() != mHost.getHandler().getLooper()) {
throw new IllegalStateException("Must be called from main thread of fragment host");
}
if (!allowStateLoss) {
checkStateLoss();
}
if (mTmpRecords == null) {
mTmpRecords = new ArrayList<>();
mTmpIsPop = new ArrayList<>();
}
mExecutingActions = true;
try {
executePostponedTransaction(null, null);
} finally {
mExecutingActions = false;
}
}
FragmentManagerImpl#executePostponedTransaction
private void executePostponedTransaction(ArrayList<BackStackRecord> records,ArrayList<Boolean> isRecordPop) {
int numPostponed = mPostponedTransactions == null ? 0 : mPostponedTransactions.size();
for (int i = 0; i < numPostponed; i++) {
StartEnterTransitionListener listener = mPostponedTransactions.get(i);
if (records != null && !listener.mIsBack) {
int index = records.indexOf(listener.mRecord);
if (index != -1 && isRecordPop.get(index)) {
listener.cancelTransaction();
continue;
}
}
if (listener.isReady() || (records != null
&& listener.mRecord.interactsWith(records, 0, records.size()))) {
mPostponedTransactions.remove(i);
i--;
numPostponed--;
int index;
if (records != null && !listener.mIsBack
&& (index = records.indexOf(listener.mRecord)) != -1
&& isRecordPop.get(index)) {
// This is popping a postponed transaction
listener.cancelTransaction();
} else {
listener.completeTransaction();
}
}
}
}
FragmentManagerImpl#generateOpsForPendingActions
private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isPop) {
int numActions;
synchronized (this) {
if (mPendingActions == null || mPendingActions.size() == 0) {
return false;
}
numActions = mPendingActions.size();
for (int i = 0; i < numActions; i++) {
mPendingActions.get(i).generateOps(records, isPop);
}
mPendingActions.clear();
mHost.getHandler().removeCallbacks(mExecCommit);
}
return numActions > 0;
}
FragmentManagerImpl#optimizeAndExecuteOps
//優化回退棧操作,一個transaction被加入棧後,然後又被彈出,這個回退棧記錄將被優化
private void optimizeAndExecuteOps(ArrayList<BackStackRecord> records,ArrayList<Boolean> isRecordPop) {
if (records == null || records.isEmpty()) {
return;
}
if (isRecordPop == null || records.size() != isRecordPop.size()) {
throw new IllegalStateException("Internal error with the back stack records");
}
// Force start of any postponed transactions that interact with scheduled transactions:
executePostponedTransaction(records, isRecordPop);
final int numRecords = records.size();
int startIndex = 0;
for (int recordNum = 0; recordNum < numRecords; recordNum++) {
final boolean canOptimize = records.get(recordNum).mAllowOptimization;
if (!canOptimize) {
// execute all previous transactions
if (startIndex != recordNum) {
executeOpsTogether(records, isRecordPop, startIndex, recordNum);
}
// execute all unoptimized pop operations together or one add operation
int optimizeEnd = recordNum + 1;
if (isRecordPop.get(recordNum)) {
while (optimizeEnd < numRecords
&& isRecordPop.get(optimizeEnd)
&& !records.get(optimizeEnd).mAllowOptimization) {
optimizeEnd++;
}
}
executeOpsTogether(records, isRecordPop, recordNum, optimizeEnd);
startIndex = optimizeEnd;
recordNum = optimizeEnd - 1;
}
}
if (startIndex != numRecords) {
executeOpsTogether(records, isRecordPop, startIndex, numRecords);
}
}
FragmentManagerImpl#doPendingDeferredStart
void doPendingDeferredStart() {
if (mHavePendingDeferredStart) {
boolean loadersRunning = false;
for (int i = 0; i < mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null && f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
if (!loadersRunning) {
mHavePendingDeferredStart = false;
startPendingDeferredFragments();
}
}
}
FragmentManagerImpl#startPendingDeferredFragments
void startPendingDeferredFragments() {
if (mActive == null) return;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
performPendingDeferredStart(f);
}
}
}
上面程式碼中首先判斷mActive中不為空,這個mActive是FragmentManager中用來儲存Fragment。它在makeActive方法中初始化:
FragmentManagerImpl#makeActive
void makeActive(Fragment f) {
if (f.mIndex >= 0) {
return;
}
if (mAvailIndices == null || mAvailIndices.size() <= 0) {
if (mActive == null) {
mActive = new ArrayList<Fragment>();
}
f.setIndex(mActive.size(), mParent);
mActive.add(f);
} else {
f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent);
mActive.set(f.mIndex, f);
}
if (DEBUG) Log.v(TAG, "Allocated fragment index " + f);
}
我們可以看到在addFragment方法中呼叫了makeActive方法:
FragmentManagerImpl#addFragment
public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (mAdded == null) {
mAdded = new ArrayList<Fragment>();
}
if (DEBUG) Log.v(TAG, "add: " + fragment);
makeActive(fragment);
if (!fragment.mDetached) {
if (mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
mAdded.add(fragment);
fragment.mAdded = true;
fragment.mRemoving = false;
if (fragment.mView == null) {
fragment.mHiddenChanged = false;
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
moveToState(fragment);
}
}
}
繼續檢視的話,我們可以看到addFragment的呼叫是在FragmentManagerImpl的onCreateView方法中,而在前面可以知道這裡的onCreateView方法是由FragmentController分發而來:
FragmentManagerImpl#onCreateView
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
if (!"fragment".equals(name)) {
return null;
}
String fname = attrs.getAttributeValue(null, "class");
TypedArray a = context.obtainStyledAttributes(attrs, FragmentTag.Fragment);
if (fname == null) {
fname = a.getString(FragmentTag.Fragment_name);
}
int id = a.getResourceId(FragmentTag.Fragment_id, View.NO_ID);
String tag = a.getString(FragmentTag.Fragment_tag);
a.recycle();
if (!Fragment.isSupportFragmentClass(mHost.getContext(), fname)) {
// Invalid support lib fragment; let the device's framework handle it.
// This will allow android.app.Fragments to do the right thing.
return null;
}
int containerId = parent != null ? parent.getId() : 0;
if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
throw new IllegalArgumentException(attrs.getPositionDescription()
+ ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
}
// If we restored from a previous state, we may already have
// instantiated this fragment from the state and should use
// that instance instead of making a new one.
Fragment fragment = id != View.NO_ID ? findFragmentById(id) : null;
if (fragment == null && tag != null) {
fragment = findFragmentByTag(tag);
}
if (fragment == null && containerId != View.NO_ID) {
fragment = findFragmentById(containerId);
}
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
+ Integer.toHexString(id) + " fname=" + fname
+ " existing=" + fragment);
if (fragment == null) {
fragment = Fragment.instantiate(context, fname);
fragment.mFromLayout = true;
fragment.mFragmentId = id != 0 ? id : containerId;
fragment.mContainerId = containerId;
fragment.mTag = tag;
fragment.mInLayout = true;
fragment.mFragmentManager = this;
fragment.mHost = mHost;
fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
addFragment(fragment, true);
} else if (fragment.mInLayout) {
// A fragment already exists and it is not one we restored from
// previous state.
throw new IllegalArgumentException(attrs.getPositionDescription()
+ ": Duplicate id 0x" + Integer.toHexString(id)
+ ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
+ " with another fragment for " + fname);
} else {
// This fragment was retained from a previous instance; get it
// going now.
fragment.mInLayout = true;
fragment.mHost = mHost;
// If this fragment is newly instantiated (either right now, or
// from last saved state), then give it the attributes to
// initialize itself.
if (!fragment.mRetaining) {
fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
}
}
// If we haven't finished entering the CREATED state ourselves yet,
// push the inflated child fragment along.
if (mCurState < Fragment.CREATED && fragment.mFromLayout) {
moveToState(fragment, Fragment.CREATED, 0, 0, false);
} else {
moveToState(fragment);
}
if (fragment.mView == null) {
throw new IllegalStateException("Fragment " + fname
+ " did not create a view.");
}
if (id != 0) {
fragment.mView.setId(id);
}
if (fragment.mView.getTag() == null) {
fragment.mView.setTag(tag);
}
return fragment.mView;
}
FragmentController#onCreateView
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
}
FragmentManagerImpl#performPendingDeferredStart
public void performPendingDeferredStart(Fragment f) {
if (f.mDeferStart) {
if (mExecutingActions) {
// Wait until we're done executing our pending transactions
mHavePendingDeferredStart = true;
return;
}
f.mDeferStart = false;
moveToState(f, mCurState, 0, 0, false);
}
}
FragmentManagerImpl#moveToState
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.mAdded || f.mDetached) && newState > Fragment.CREATED) {
newState = Fragment.CREATED;
}
if (f.mRemoving && newState > f.mState) {
// While removing a fragment, we can't change it to a higher state.
newState = f.mState;
}
// Defer start if requested; don't allow it to move to STARTED or higher
// if it's not already started.
if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
newState = Fragment.STOPPED;
}
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.
if (f.mFromLayout && !f.mInLayout) {
return;
}
if (f.getAnimatingAway() != null) {
// The fragment is currently being animated... but! Now we