moveToState是FM中一个相当长的函数,但Fragment任何的操作add,remove …最终都会调用这个函数,从字面上可以理解,fragment要从当前状态切到newState里面干些什么都在这个函数中。
Fragment有六种State,初始状态是INITIALIZING:
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.
int mState = INITIALIZING;
那么看看 对Fragment的各个操作分别是如何调用moveToState的。
操作 | 调用 | 说明 |
---|---|---|
addFragment | moveToState(fragment) 实质调用moveToState(f, mCurState, 0, 0, false); | |
attachFragment | moveToState(fragment, mCurState, transition, transitionStyle, false); |
可以看出,addFragment,attachFragment的newState都是向fm的域mCurState看齐的
在fm中只有一处对mCurState进行赋值。
void moveToState(int newState, int transit, int transitStyle, boolean always) {
if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No host");
}
if (!always && mCurState == newState) {
return;
}
mCurState = newState;
if (mActive != null) {
boolean loadersRunning = false;
for (int i=0; iif (f != null) {
moveToState(f, newState, transit, transitStyle, false);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
if (!loadersRunning) {
startPendingDeferredFragments();
}
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onSupportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
}
该函数被moveToState(int newState, boolean always)所调用,而后者又被
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);
}
那么上面这些函数又会被谁调用到呢?FragmentActivity!
FragmentActivity生命周期 | fm被调用函数 |
---|---|
onCreate | dispatchCreate() |
onStart() | dispatchStart() 及 dispatchActivityCreated() |
onStop() | dispatchStop() |
onPostResume() | dispatchResume() |
fm中mCurState的值是完全随着其FragmentActivity生命周期变化而变化的,那么也就说明每当有fragment 添加进来的时候,其newState都是和其父FragmentActivity的当前生命周期是相对应的。
长长的函数,提炼一下
if (f.mState < newState) {
switch (f.mState) {
case Fragment.INITIALIZING:
//some code
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
//some code
}
case Fragment.ACTIVITY_CREATED:
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
//some code
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
//some code
}
}
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
//some code
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
//some code
}
case Fragment.STOPPED:
if (newState < Fragment.STOPPED) {
//some code
}
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
//some code
}
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
//some code
}
}
}
f.mState = newState;
在switch的每个case里是没有添加break的,也就是从fragment当前的状态开始一直执行掉剩下的所有case,所以fragment添加后,不论其父FragmentActivity处于什么状态,他都会从头执行自己的生命周期。
当fragment刚添加到父组件中时,f.mState < newState
f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
f.mCalled = false;
f.onAttach(mHost.getContext());
之前fragmnet是一个完全独立的对象,和父Fragment或父FragmentActivity一点关系没有,那么经过了INITIALIZING这一步,算是认祖归宗了。那么onAttach的意义也在于此。
而后在fragment.mFromLayout条件为true时会执行如下代码
if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
}
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
/* some code */
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
通过performCreateView间接回调onCreateView得到fragment的View,拿到该View后就会回调onViewCreated
而后在fragment.mFromLayout条件为false时会执行:
根据mContainerId得到View容器container,并且将fragment的onCreateView所返回的View添加到容器container中。
而后顺序调用
f.onViewCreated(f.mView, f.mSavedFragmentState)
f.performActivityCreated(f.mSavedFragmentState)
Fragment.ACTIVITY_CREATED,Fragment.STOPPED,Fragment.STARTED没有什么实质的工作,走了个过场。
上面的过程基本上可以一览fragment的添加过程:
1.将fragment和父组件关联起来。
2.将fragment中的View添加到父组件的View容器中,这样就能显示出fragment的View出来了。