一、整体概述
在 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 开发中这两个重要组件的使用。