Fragment启动过程,从getFragmentManager开始
Posted yuminfeng728
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
Fragment的学习使用