Activity与Fragment的生命周期是一个老生常谈的话题,网上最常见的图是这个:
还有这个:
但是这个图并没有说明Activity和Fragment的每个阶段下,是Fragment的方法先调用还是Activity的方法先调用。于是我尝试了探究了一下。
场景一
我的代码如下:
Activity1.java
public class Activity1 extends AppCompatActivity {
FragmentManager fragmentManager;
FrameLayout frameLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
log("onCreate");
setContentView(R.layout.activity_simple);
frameLayout = (FrameLayout) findViewById(R.id.container);
fragmentManager = getSupportFragmentManager();
if (savedInstanceState == null) {
fragmentManager.beginTransaction()
.add(R.id.container,SimpleFragment1.getInstance("fragment") , "fragment")
.commit();
}
}
@Override
protected void onStart() {
super.onStart();
log("onStart");
frameLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
protected void onResume() {
super.onResume();
log("onResume");
}
@Override
protected void onPause() {
super.onPause();
log("onPause");
}
@Override
protected void onStop() {
super.onStop();
log("onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
log("onDestroy");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
log("onSaveInstanceState");
}
private void log(String s) {
Log.i("tag", "Activity1 -- " + s);
}
}
SimpleFragment1.java
public class SimpleFragment1 extends Fragment {
private String str;
private int num=1;
public SimpleFragment1() {
}
public static SimpleFragment1 getInstance(String s) {
SimpleFragment1 fragment = new SimpleFragment1();
Bundle b = new Bundle();
b.putString("string", s);
fragment.setArguments(b);
return fragment;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
log("onAttach");
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
log("onCreate");
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
log("onCreateView");
str = getArguments().getString("string");
View v = inflater.inflate(R.layout.fragment_simple, container,false);
TextView text = (TextView) v.findViewById(R.id.textview);
text.setText(str);
return v;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
log("onActivityCreated");
}
@Override
public void onStart() {
super.onStart();
log("onStart");
}
@Override
public void onResume() {
super.onResume();
log("onResume");
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
log("onSaveInstanceState");
}
@Override
public void onPause() {
super.onPause();
log("onPause");
}
@Override
public void onStop() {
super.onStop();
log("onStop");
}
@Override
public void onDestroyView() {
super.onDestroyView();
log("onDestroyView");
}
@Override
public void onDestroy() {
super.onDestroy();
log("onDestroy");
}
@Override
public void onDetach() {
super.onDetach();
log("onDetach");
}
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
log("isHidden:" + hidden);
}
private void log(String s) {
Log.v("tag","Fragment"+num +" -- " + s);
}
}
布局:
activity_simple.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
fragment_simple.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:textSize="20sp" />
</RelativeLayout>
启动Activity时,生命周期函数调用如下:
当按锁屏键、 多任务键或者直接按桌面键进入桌面时,这种情况我暂且称之为Activity挂起状态 ,这种情况下生命周期函数调用如下:
当Activity从后台返回(再次按锁屏键打开屏幕,或从多任务界面回到当前应用程序界面)时,这种情况暂且称为挂起-唤醒 状态。生命周期函数调用如下:
当Activity销毁时:
当旋转屏幕时,Activity和Fragment会被销毁,然后再重建:
注意,上面的场景是,我在Activity的生命周期函数中super
调用部分之后在打印log的。
场景二
于是我又做了这样的实验,我将log打印语句放在super
之前,我将Activity的代码改为这样(其他代码不变):
Activity2.java
public class Activity2 extends AppCompatActivity {
FragmentManager fragmentManager;
FrameLayout frameLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
//在super之前打印log
log("onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
frameLayout = (FrameLayout) findViewById(R.id.container);
fragmentManager = getSupportFragmentManager();
if (savedInstanceState == null) {
fragmentManager.beginTransaction()
.add(R.id.container,SimpleFragment1.getInstance("fragment") , "fragment")
.commit();
}
}
@Override
protected void onStart() {
log("onStart");
super.onStart();
frameLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
protected void onResume() {
log("onResume");
super.onResume();
}
@Override
protected void onPause() {
log("onPause");
super.onPause();
}
@Override
protected void onStop() {
log("onStop");
super.onStop();
}
@Override
protected void onDestroy() {
log("onDestroy");
super.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
log("onSaveInstanceState");
super.onSaveInstanceState(outState);
}
private void log(String s) {
Log.i("tag", "Activity2 -- " + s);
}
}
Activity创建时,生命周期函数调用如下:
Activity挂起时:
注意:与场景一不同,场景一是先打印了Fragment的生命周期函数,再打印了对应Activity的生命周期函数。在场景二下,是先打印了Activity的
onPause
再打印Fragment的onPause
,onSaveInstanceState
和onStop
都是先打印了Activity再打印Fragment的。
说明Activity中的这个super.onXXXX
从一定程度上与Fragment的生命周期相关。后面继续分析此处
先看在场景二下,Activity的挂起-唤醒状态:
Activity的销毁:
旋转屏幕:
可以看到,在场景二下,logcat中打印的消息告诉我们,每个生命周期阶段,都是Activity的生命周期函数先执行,然后再执行Fragment的。
Activity生命周期中的super.onXXX与Fragment的关系分析
以Activity1中onCreate
的super.onCreate(savedInstanceState)
为例分析:
因为我的Activity1继承自AppCompatActivity,AppCompatActivity的onCreate
如下:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
final AppCompatDelegate delegate = getDelegate();
delegate.installViewFactory();
delegate.onCreate(savedInstanceState);
if (delegate.applyDayNight() && mThemeId != 0) {
// If DayNight has been applied, we need to re-apply the theme for
// the changes to take effect. On API 23+, we should bypass
// setTheme(), which will no-op if the theme ID is identical to the
// current theme ID.
if (Build.VERSION.SDK_INT >= 23) {
onApplyThemeResource(getTheme(), mThemeId, false);
} else {
setTheme(mThemeId);
}
}
super.onCreate(savedInstanceState);
}
在最后又调用了super.onCreate(savedInstanceState)
,而AppCompatActivity是继承自FragmentActivity的,所以可以看出与Fragment一定存在某种联系。
FragmentActivity的onCreate
protected void onCreate(@Nullable Bundle savedInstanceState) {
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;
}
mFragments.dispatchCreate();
}
最后一句mFragments.dispatchCreate();
,mFragments是一个FragmentController
。 FragmentController是Activity中所有Fragment的生命周期管理者。其dispatchCreate
如下:
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
mFragmentManager是一个FragmentManagerImpl
类的实例,FragmentManagerImpl
继承自FragmentManager
类。这里我们把mFragmentManager看成是Fragment的存放容器就可以了。
dispatchCreate()
的实现如下:
public void dispatchCreate() {
mStateSaved = false;
mExecutingActions = true;
moveToState(Fragment.CREATED, false);
mExecutingActions = false;
}
moveToState()
的实现如下,部分代码省略:
void moveToState(int newState, boolean always) {
.......
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);
//标记处1
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) {
//标记处2
moveFragmentToExpectedState(f);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
.......
}
}
(在上面代码片段中我做了两个标记处,后面接着分析这两处)
moveToState中又调用了moveFragmentToExpectedState()
,从函数名可知,实际做的就是将每个fragment都转移到各自对应的状态。
Fragment定义了如下几种状态:
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是位于INITIALIZING 状态。
moveFragmentToExpectedState(Fragment f)
函数:
void moveFragmentToExpectedState(Fragment f) {
....
moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
if (f.mView != null) {
// Move the view if it is out of order
Fragment underFragment = findFragmentUnder(f);
if (underFragment != null) {
final View underView = underFragment.mView;
// make sure this fragment is in the right order.
final ViewGroup container = f.mContainer;
int underIndex = container.indexOfChild(underView);
int viewIndex = container.indexOfChild(f.mView);
if (viewIndex < underIndex) {
container.removeViewAt(viewIndex);
container.addView(f.mView, underIndex);
}
}
...
}
}
其中调用了moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive)
。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.mState < newState) {
....
switch (f.mState) {
case Fragment.INITIALIZING:
....
//1.在这里调用了Fragment的onAttach()
f.onAttach(mHost.getContext());
...
dispatchOnFragmentAttached(f, mHost.getContext(), false);
if (!f.mRetaining) {
//2.在performCreate内部调用了Fragment的onCreate()
f.performCreate(f.mSavedFragmentState);
dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
} else {
f.restoreChildFragmentState(f.mSavedFragmentState);
//*****注意:这里将Fragment的状态设置为CREATED
f.mState = Fragment.CREATED;
}
f.mRetaining = false;
if (f.mFromLayout) {
//3.在performCreateView中调用了Fragment的onCreateView()
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:
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
....
//4.在performActivityCreated()中调用了Fragment的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) {
f.performStart();
dispatchOnFragmentStarted(f, false);
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
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) {
f.performPause();
dispatchOnFragmentPaused(f, false);
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
f.performStop();
dispatchOnFragmentStopped(f, false);
}
case Fragment.STOPPED:
if (newState < Fragment.STOPPED) {
f.performReallyStop();
}
case Fragment.ACTIVITY_CREATED:
.....
case Fragment.CREATED:
.....
}
}
}
该函数中就是对Fragment的各种不同的状态进行处理,一开始Fragment是处于INITIALIZING状态的,在INITIALIZING对应的case 语句中,相应的调用了Fragment的onAttach()
,onCreate()
和onCreateView()
,我在代码中也写了注释。在调用了onCreate
之后,同时Fragment的状态会被设置为CREATED。
还记得moveToState(int newState, boolean always)
中的标记处一和标记处二吗,记不得就再回去看看。这两处标记处都是调用了关键函数moveToState
。我们可以这么理解,标记处一的关键函数是对INITIALIZING状态的Fragment进行处理,当执行完标记处一的关键函数后,Fragment的状态被设置为CREATED,然后到标记处二,对CREATED状态的Fragment再进行处理。
下面我们分析关键函数中对于CREATED状态的case语句:
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
....
//在performActivityCreated()中调用了Fragment的onActivityCreated()
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
在performActivityCreated()
函数中,调用了Fragment的onActivityCreated():
void performActivityCreated(Bundle savedInstanceState) {
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
}
mState = ACTIVITY_CREATED;
mCalled = false;
onActivityCreated(savedInstanceState);
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onActivityCreated()");
}
if (mChildFragmentManager != null) {
mChildFragmentManager.dispatchActivityCreated();
}
}
至此,Fragment的创建过程基本完毕,Fragment的创建时生命周期函数可以解释为:在INITIALIZING中执行了onAttach()
,onCreate()
和onCreateView()
,在CREATED中执行了onActivityCreated()
。
其他的Fragment生命周期函数也和上面分析的onCreate
类似,其本质都是在关键函数中对各种状态进行处理并触发生命周期回调函数。
总结
实际上同阶段下Activity的生命周期函数是Fragment的生命周期函数入口,这里同阶段是指Activity的onCreate
对应Fragment的onCreate
,Activity的onResume
对应Fragment的onResume
之类的。
Activity的super.onXXXX中正是调用了Fragment的生命周期函数onXXXX。这也就解释了场景一和场景二中为什么在不同的地方打印log结果输出是不一样的。
关于Activity与Fragment的生命周期,github上还有一位大神画了这样一张图,地址在这里:https://github.com/xxv/android-lifecycle
其实我还有一点没理解,在场景一中,由于我log语句是写在super
之后的,为啥是Activity1的onResume
先执行,再执行Fragment1的onResume
?如果有知道的朋友请告诉我,谢谢。