概述
时至今日,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
// want to move our state back up. Give up on waiting for the
// animation, move to whatever the final state should be once
// the animation is done, and then we can proceed from there.
f.setAnimatingAway(null);
moveToState(f, f.getStateAfterAnimating(), 0, 0, true);
}
switch (f.mState) {
case Fragment.INITIALIZING: //初始化状态
if (f.mSavedFragmentState != null) {
f.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
f.mTarget = getFragment(f.mSavedFragmentState,
FragmentManagerImpl.TARGET_STATE_TAG);
if (f.mTarget != null) {
f.mTargetRequestCode = f.mSavedFragmentState.getInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
}
f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
if (!f.mUserVisibleHint) {
f.mDeferStart = true;
if (newState > Fragment.STOPPED) {
newState = Fragment.STOPPED;
}
}
}
f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
f.mCalled = false;
//step 1: 执行onAttach
f.onAttach(mHost.getContext());
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()");
}
if (f.mParentFragment == null) {
mHost.onAttachFragment(f);
} else {
f.mParentFragment.onAttachFragment(f);
}
dispatchOnFragmentAttached(f, mHost.getContext(), false);
if (!f.mRetaining) {
//step 2: 执行onCreate
f.performCreate(f.mSavedFragmentState);
dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
} else {
f.restoreChildFragmentState(f.mSavedFragmentState);
f.mState = Fragment.CREATED;
}
f.mRetaining = false;
//判断该fragment是否从布局中实例化
if (f.mFromLayout) {
// For fragments that are part of the content view
// layout, we need to instantiate the view immediately
// and the inflater will take care of adding it.
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
if (Build.VERSION.SDK_INT >= 11) {
ViewCompat.setSaveFromParentEnabled(f.mView, false);
} else {
f.mView = NoSaveStateFrameLayout.wrap(f.mView);
}
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
} else {
f.mInnerView = null;
}
}
case Fragment.CREATED: //created 状态
if (newState > Fragment.CREATED) {
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
if (f.mContainerId == View.NO_ID) {
throwException(new IllegalArgumentException(
"Cannot create fragment " + f + " for a container view with no id"));
}
container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
String resName;
try {
resName = f.getResources().getResourceName(f.mContainerId);
} catch (NotFoundException e) {
resName = "unknown";
}
throwException(new IllegalArgumentException(
"No view found for id 0x" + Integer.toHexString(f.mContainerId) + " ("+ resName + ") for fragment " + f));
}
}
f.mContainer = container;
//step 3:执行onCreateView
f.mView = f.performCreateView(f.getLayoutInflater(f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
if (Build.VERSION.SDK_INT >= 11) {
ViewCompat.setSaveFromParentEnabled(f.mView, false);
} else {
f.mView = NoSaveStateFrameLayout.wrap(f.mView);
}
if (container != null) {
container.addView(f.mView);
}
if (f.mHidden) {
f.mView.setVisibility(View.GONE);
}
//step 4:执行onViewCreated
f.onViewCreated(f.mView, f.mSavedFragmentState);
dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,false);
// Only animate the view if it is visible. This is done after
// dispatchOnFragmentViewCreated in case visibility is changed
f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE) && f.mContainer != null;
} else {
f.mInnerView = null;
}
}
//step 4: 执行onActivityCreated
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
case Fragment.ACTIVITY_CREATED:
if (newState > Fragment.ACTIVITY_CREATED) {
f.mState = Fragment.STOPPED;
}
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.performStart();
dispatchOnFragmentStarted(f, false);
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.performResume();
dispatchOnFragmentResumed(f, false);
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();
dispatchOnFragmentPaused(f, false);
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
f.performStop();
dispatchOnFragmentStopped(f, false);
}
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) {
if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
if (f.mView != null) {
// Need to save the current view state if not
// done already.
if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
f.performDestroyView();
dispatchOnFragmentViewDestroyed(f, false);
if (f.mView != null && f.mContainer != null) {
Animation anim = null;
if (mCurState > Fragment.INITIALIZING && !mDestroyed
&& f.mView.getVisibility() == View.VISIBLE
&& f.mPostponedAlpha >= 0) {
anim = loadAnimation(f, transit, false,
transitionStyle);
}
f.mPostponedAlpha = 0;
if (anim != null) {
final Fragment fragment = f;
f.setAnimatingAway(f.mView);
f.setStateAfterAnimating(newState);
final View viewToAnimate = f.mView;
anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener(
viewToAnimate, anim) {
@Override
public void onAnimationEnd(Animation animation) {
super.onAnimationEnd(animation);
if (fragment.getAnimatingAway() != null) {
fragment.setAnimatingAway(null);
moveToState(fragment, fragment.getStateAfterAnimating(),
0, 0, false);
}
}
});
f.mView.startAnimation(anim);
}
f.mContainer.removeView(f.mView);
}
f.mContainer = null;
f.mView = null;
f.mInnerView = null;
}
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (mDestroyed) {
if (f.getAnimatingAway() != null) {
// The fragment's containing activity is
// being destroyed, but this fragment is
// currently animating away. Stop the
// animation right now -- it is not needed,
// and we can't wait any more on destroying
// the fragment.
View v = f.getAnimatingAway();
f.setAnimatingAway(null);
v.clearAnimation();
}
}
if (f.getAnimatingAway() != null) {
// We are waiting for the fragment's view to finish
// animating away. Just make a note of the state
// the fragment now should move to once the animation
// is done.
f.setStateAfterAnimating(newState);
newState = Fragment.CREATED;
} else {
if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
if (!f.mRetaining) {
f.performDestroy();
dispatchOnFragmentDestroyed(f, false);
} else {
f.mState = Fragment.INITIALIZING;
}
f.performDetach();
dispatchOnFragmentDetached(f, false);
if (!keepActive) {
if (!f.mRetaining) {
makeInactive(f);
} else {
f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
}
}
}
}
}
}
if (f.mState != newState) {
Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
+ "expected state " + newState + " found " + f.mState);
f.mState = newState;
}
}
上面方法通过不断改变当前的状态来完成生命周期的转变。其中,Fragment的onAttach和onCreate都是在Fragment.INITIALIZING中执行。onCreateView则要根据Fragment的布局是否从layout file中初始化。是则在Fragment.INITIALIZING中执行,否则是在Fragment.CREATED中执行。onActivityCreate是在Fragment.CREATED中执行。
以上便是Fragment的启动过程源码分析。