一、整体概述
在 Android 开发中,Fragment
和 Activity
是构建用户界面的关键组件。Activity
作为应用的重要交互载体,管理着应用的整体界面和生命周期;而 Fragment
则是轻量级的 Activity
,可嵌入到 Activity
中,实现界面的模块化和复用。理解 Fragment
生命周期与 Activity
生命周期的关系,对于开发高质量、可维护的 Android 应用至关重要。本文将从源码层面深入剖析这两者生命周期之间的关联,详细阐述它们是如何相互影响和协同工作的。
二、Activity 生命周期基础回顾
2.1 Activity 生命周期方法概述
Activity
的生命周期包含多个重要方法,这些方法在不同阶段被系统调用,开发者可重写这些方法实现特定逻辑。主要方法如下:
onCreate(Bundle savedInstanceState)
:Activity
首次创建时调用,用于初始化布局、数据等。onStart()
:Activity
即将可见时调用。onResume()
:Activity
获得焦点并开始与用户交互时调用。onPause()
:Activity
失去焦点但仍可见时调用,常用于保存数据、释放资源。onStop()
:Activity
不再可见时调用。onDestroy()
:Activity
即将销毁时调用,用于释放所有资源。onRestart()
:Activity
从停止状态重新启动时调用。
2.2 ActivityThread 对 Activity 生命周期的管理
ActivityThread
是 Android 应用的主线程类,负责管理 Activity
的生命周期。以下是启动 Activity
的关键代码:
ini
// ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// 创建 Activity 实例
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
// 调用 Activity 的 onResume 方法
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
}
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 获取 Activity 的组件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
// 创建 Activity 类加载器
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
// 通过反射创建 Activity 实例
Activity activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
Context appContext = createBaseContextForActivity(r, activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
// 调用 Activity 的 onCreate 方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
// 调用 Activity 的 onStart 方法
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
// 调用 Activity 的 onRestoreInstanceState 方法
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
// 调用 Activity 的 onPostCreate 方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
return activity;
}
从上述代码可以看出,ActivityThread
通过一系列方法调用,依次触发 Activity
的 onCreate
、onStart
等生命周期方法。
2.3 Instrumentation 对 Activity 生命周期的监控
Instrumentation
类负责监控 Activity
的生命周期方法调用。例如,callActivityOnCreate
方法会调用 Activity
的 onCreate
方法:
scss
// Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.onCreate(icicle);
postPerformCreate(activity);
}
Instrumentation
在 Activity
生命周期方法调用前后添加了一些预处理和后处理逻辑,确保 Activity
生命周期的正常执行。
三、Fragment 生命周期基础回顾
3.1 Fragment 生命周期方法概述
Fragment
的生命周期与 Activity
有相似之处,也有独特方法。主要方法如下:
onAttach(Context context)
:Fragment
与Activity
关联时调用。onCreate(Bundle savedInstanceState)
:Fragment
被创建时调用,用于初始化数据。onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
:创建Fragment
的视图时调用,返回View
对象。onViewCreated(View view, Bundle savedInstanceState)
:Fragment
的视图创建完成后调用,可用于初始化视图组件。onActivityCreated(Bundle savedInstanceState)
:关联的Activity
的onCreate
方法执行完成后调用。onStart()
:Fragment
即将可见时调用。onResume()
:Fragment
获得焦点并开始与用户交互时调用。onPause()
:Fragment
失去焦点但仍可见时调用。onStop()
:Fragment
不再可见时调用。onDestroyView()
:Fragment
的视图被销毁时调用。onDestroy()
:Fragment
即将被销毁时调用。onDetach()
:Fragment
与Activity
解除关联时调用。
3.2 FragmentManager 对 Fragment 生命周期的管理
FragmentManager
负责管理 Fragment
的生命周期。当 Activity
启动时,FragmentManager
会根据 Activity
的生命周期状态来管理 Fragment
的生命周期。以下是 FragmentManager
中处理 Fragment
生命周期的部分代码:
ini
// FragmentManager.java
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
if (f.mState <= newState) {
switch (f.mState) {
case Fragment.INITIALIZING:
if (newState > Fragment.INITIALIZING) {
f.onAttach(mHost.getContext());
if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
}
f.mState = Fragment.CREATED;
}
break;
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (f.mFromLayout) {
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
f.mState = Fragment.ACTIVITY_CREATED;
}
break;
case Fragment.ACTIVITY_CREATED:
if (newState > Fragment.ACTIVITY_CREATED) {
if (!f.mFromLayout) {
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
f.mState = Fragment.STARTED;
}
break;
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
f.performResume();
f.mState = Fragment.RESUMED;
}
break;
}
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
f.performPause();
f.mState = Fragment.STARTED;
}
break;
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
f.performStop();
f.mState = Fragment.ACTIVITY_CREATED;
}
break;
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
if (f.mView != null) {
f.performDestroyView();
}
f.mState = Fragment.CREATED;
}
break;
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (!f.mRetaining) {
f.performDestroy();
}
f.onDetach();
f.mState = Fragment.INITIALIZING;
}
break;
}
}
f.mState = newState;
}
FragmentManager
通过 moveToState
方法根据 Fragment
的当前状态和目标状态,调用相应的生命周期方法,确保 Fragment
生命周期的正确流转。
四、Activity 与 Fragment 生命周期关系的打通
4.1 关联建立阶段
4.1.1 Activity 创建时关联 Fragment
当 Activity
启动时,Activity
的 onCreate
方法会被调用。在 onCreate
方法中,会涉及到 Fragment
的恢复和创建操作。以下是 Activity
的 onCreate
方法相关代码:
less
// Activity.java
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
// ...
}
restoreAllState
方法:用于恢复之前保存的Fragment
状态。如果Activity
是因为配置变化(如屏幕旋转)而重新创建,会从savedInstanceState
中恢复Fragment
的状态。dispatchCreate
方法:通知FragmentManager
开始处理Fragment
的创建过程。FragmentManager
会遍历所有Fragment
,调用其performCreate
方法。
4.1.2 Fragment 与 Activity 关联
在 FragmentManager
的 dispatchCreate
方法中,会调用 Fragment
的 performCreate
方法:
ini
// FragmentManager.java
void dispatchCreate() {
mStateSaved = false;
mDestroyed = false;
for (int i = 0; i < mActive.size(); i++) {
Fragment f = mActive.valueAt(i);
if (f != null) {
if (!f.mIsCreated) {
f.performCreate(f.mSavedFragmentState);
}
}
}
}
// Fragment.java
void performCreate(Bundle savedInstanceState) {
mChildFragmentManager.noteStateNotSaved();
mState = Fragment.CREATED;
onCreate(savedInstanceState);
mIsCreated = true;
}
在 performCreate
方法中,会调用 Fragment
的 onCreate
方法,同时将 Fragment
的状态设置为 CREATED
。此时,Fragment
与 Activity
建立了初步关联。
4.2 视图创建阶段
4.2.1 Activity 视图创建时触发 Fragment 视图创建
在 Activity
的视图创建过程中,FragmentManager
会根据 Fragment
的状态来决定是否创建 Fragment
的视图。当 Fragment
的状态从 CREATED
转变为 ACTIVITY_CREATED
时,会触发视图创建。以下是 FragmentManager
的 moveToState
方法相关代码:
java
// FragmentManager.java
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
if (f.mState <= newState) {
switch (f.mState) {
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (f.mFromLayout) {
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
f.mState = Fragment.ACTIVITY_CREATED;
}
break;
// ...
}
}
// ...
}
performCreateView
方法:调用Fragment
的onCreateView
方法,创建Fragment
的视图。onViewCreated
方法:在视图创建完成后调用,可用于初始化视图组件。
4.2.2 Fragment 视图与 Activity 视图的关联
Fragment
的视图创建完成后,会被添加到 Activity
的视图层次结构中。在 FragmentManager
中,会通过 FragmentContainer
来管理 Fragment
视图的添加和移除。具体的添加逻辑在 FragmentManager
的 addFragment
方法中实现:
scss
// FragmentManager.java
void addFragment(Fragment fragment, boolean moveToStateNow) {
mAdded.add(fragment);
if (moveToStateNow) {
moveToState(fragment, mCurState, 0, 0, false);
}
}
通过 addFragment
方法,Fragment
的视图被添加到 Activity
的视图层次结构中,实现了视图的关联。
4.3 可见性变化阶段
4.3.1 Activity 可见性变化触发 Fragment 可见性变化
当 Activity
的可见性发生变化时,会调用 FragmentManager
的相应方法来通知 Fragment
。例如,当 Activity
的 onStart
方法被调用时,会调用 FragmentManager
的 dispatchStart
方法
scss
// Activity.java
protected void onStart() {
super.onStart();
mFragments.dispatchStart();
// ...
}
// FragmentManager.java
void dispatchStart() {
mStateSaved = false;
for (int i = 0; i < mActive.size(); i++) {
Fragment f = mActive.valueAt(i);
if (f != null) {
if (f.mState < Fragment.STARTED) {
moveToState(f, Fragment.STARTED, 0, 0, false);
}
}
}
}
dispatchStart
方法会遍历所有 Fragment
,如果 Fragment
的状态小于 STARTED
,则调用 moveToState
方法将其状态转变为 STARTED
,并调用 Fragment
的 onStart
方法。
4.3.2 Fragment 可见性状态同步
同样,当 Activity
的 onResume
、onPause
、onStop
方法被调用时,会分别调用 FragmentManager
的 dispatchResume
、dispatchPause
、dispatchStop
方法,实现 Fragment
可见性状态的同步。以下是 dispatchResume
方法的代码:
scss
// Activity.java
protected void onResume() {
super.onResume();
mFragments.dispatchResume();
// ...
}
// FragmentManager.java
void dispatchResume() {
mStateSaved = false;
for (int i = 0; i < mActive.size(); i++) {
Fragment f = mActive.valueAt(i);
if (f != null) {
if (f.mState < Fragment.RESUMED) {
moveToState(f, Fragment.RESUMED, 0, 0, false);
}
}
}
}
通过这种方式,Fragment
的可见性状态与 Activity
的可见性状态保持同步。
4.4 销毁阶段
4.4.1 Activity 销毁时触发 Fragment 销毁
当 Activity
的 onDestroy
方法被调用时,会调用 FragmentManager
的 dispatchDestroy
方法:
scss
// Activity.java
protected void onDestroy() {
super.onDestroy();
mFragments.dispatchDestroy();
// ...
}
// FragmentManager.java
void dispatchDestroy() {
mDestroyed = true;
for (int i = 0; i < mActive.size(); i++) {
Fragment f = mActive.valueAt(i);
if (f != null) {
if (f.mState > Fragment.INITIALIZING) {
moveToState(f, Fragment.INITIALIZING, 0, 0, false);
}
}
}
}
dispatchDestroy
方法会遍历所有 Fragment
,将其状态转变为 INITIALIZING
,并依次调用 Fragment
的 onDestroyView
、onDestroy
、onDetach
方法。
4.4.2 Fragment 资源释放
在 Fragment
的销毁过程中,会释放其持有的资源。例如,在 onDestroyView
方法中,会销毁 Fragment
的视图:
ini
// Fragment.java
void performDestroyView() {
mChildFragmentManager.noteStateNotSaved();
mState = Fragment.CREATED;
onDestroyView();
mViewLifecycleOwner.destroy();
mViewLifecycleOwner = null;
mView = null;
mInnerView = null;
}
在 onDestroy
方法中,会销毁 Fragment
的其他资源:
ini
// Fragment.java
void performDestroy() {
mChildFragmentManager.noteStateNotSaved();
mState = Fragment.INITIALIZING;
onDestroy();
mChildFragmentManager.dispatchDestroy();
mChildFragmentManager = null;
}
在 onDetach
方法中,会解除 Fragment
与 Activity
的关联:
ini
// Fragment.java
void onDetach() {
mHost = null;
mParentFragment = null;
mFragmentManager = null;
mChildFragmentManager = null;
mActivity = null;
mCalled = true;
}
五、不同场景下的生命周期关系
5.1 正常启动和关闭 Activity
当正常启动一个包含 Fragment
的 Activity
时,Activity
和 Fragment
的生命周期方法会按照上述顺序依次调用。具体流程如下:
Activity
的onCreate
方法被调用,触发Fragment
的onAttach
和onCreate
方法。Activity
的onStart
方法被调用,触发Fragment
的onStart
方法。Activity
的onResume
方法被调用,触发Fragment
的onResume
方法。- 当关闭
Activity
时,Activity
的onPause
方法被调用,触发Fragment
的onPause
方法。 Activity
的onStop
方法被调用,触发Fragment
的onStop
方法。Activity
的onDestroy
方法被调用,触发Fragment
的onDestroyView
、onDestroy
和onDetach
方法。
5.2 屏幕旋转
当屏幕旋转时,Activity
会被销毁并重新创建。在这个过程中,Fragment
的生命周期会受到影响。为了避免 Fragment
被重复创建,可以使用 setRetainInstance(true)
方法。以下是相关源码分析:
arduino
// Fragment.java
public void setRetainInstance(boolean retain) {
mRetainInstance = retain;
if (retain) {
mDetached = false;
}
}
// FragmentManager.java
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// ...
if (f.mState > newState) {
switch (f.mState) {
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (!f.mRetaining) {
f.performDestroy();
}
f.onDetach();
f.mState = Fragment.INITIALIZING;
}
break;
// ...
}
}
// ...
}
当 mRetainInstance
为 true
时,Fragment
在 Activity
销毁时不会被销毁,而是会保留其状态,在 Activity
重新创建时直接恢复。
5.3 低内存情况
在低内存情况下,系统可能会销毁一些不常用的 Activity
和 Fragment
以释放内存。当 Activity
被销毁时,会触发 Fragment
的销毁过程。系统会调用 Activity
的 onSaveInstanceState
方法保存 Activity
和 Fragment
的状态,当 Activity
重新创建时,会从保存的状态中恢复 Fragment
。以下是 Activity
的 onSaveInstanceState
方法相关代码:
less
// Activity.java
protected void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
saveAllState
方法会保存 Fragment
的状态,以便在 Activity
重新创建时恢复。
六、总结
通过对 Activity
和 Fragment
生命周期源码的深入分析,我们可以看到它们之间的生命周期关系是紧密相连的。Activity
作为 Fragment
的容器,通过 FragmentManager
管理 Fragment
的生命周期。在 Activity
的不同生命周期阶段,会触发 Fragment
相应的生命周期方法,实现 Fragment
与 Activity
的协同工作。开发者在使用 Fragment
时,需要深入理解这种生命周期关系,确保在合适的时机进行资源的分配和释放,避免内存泄漏和性能问题。同时,对于不同的场景(如屏幕旋转、低内存情况),需要根据 Fragment
的特性进行合理的处理,以提供更好的用户体验。
以上内容从源码层面详细阐述了 Activity
和 Fragment
生命周期的关系,希望能帮助开发者更好地掌握 Android 开发中这两个重要组件的使用。