Android Fragment生命周期跟Activity生命周期原理分析

256 阅读9分钟

一、整体概述

在 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 的关键代码:

// 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 的 onCreateonStart 等生命周期方法。

2.3 Instrumentation 对 Activity 生命周期的监控

Instrumentation 类负责监控 Activity 的生命周期方法调用。例如,callActivityOnCreate 方法会调用 Activity 的 onCreate 方法:

// 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 生命周期的部分代码:

// 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 方法相关代码:

// 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 方法:

// 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 方法相关代码:

// 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 方法中实现:

// 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 方法

// 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 的 onResumeonPauseonStop 方法被调用时,会分别调用 FragmentManager 的 dispatchResumedispatchPausedispatchStop 方法,实现 Fragment 可见性状态的同步。以下是 dispatchResume 方法的代码:

// 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 方法:

// 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 的 onDestroyViewonDestroyonDetach 方法。

4.4.2 Fragment 资源释放

在 Fragment 的销毁过程中,会释放其持有的资源。例如,在 onDestroyView 方法中,会销毁 Fragment 的视图:

// Fragment.java
void performDestroyView() {
    mChildFragmentManager.noteStateNotSaved();
    mState = Fragment.CREATED;
    onDestroyView();
    mViewLifecycleOwner.destroy();
    mViewLifecycleOwner = null;
    mView = null;
    mInnerView = null;
}

在 onDestroy 方法中,会销毁 Fragment 的其他资源:

// Fragment.java
void performDestroy() {
    mChildFragmentManager.noteStateNotSaved();
    mState = Fragment.INITIALIZING;
    onDestroy();
    mChildFragmentManager.dispatchDestroy();
    mChildFragmentManager = null;
}

在 onDetach 方法中,会解除 Fragment 与 Activity 的关联:

// Fragment.java
void onDetach() {
    mHost = null;
    mParentFragment = null;
    mFragmentManager = null;
    mChildFragmentManager = null;
    mActivity = null;
    mCalled = true;
}

五、不同场景下的生命周期关系

5.1 正常启动和关闭 Activity

当正常启动一个包含 Fragment 的 Activity 时,Activity 和 Fragment 的生命周期方法会按照上述顺序依次调用。具体流程如下:

  1. Activity 的 onCreate 方法被调用,触发 Fragment 的 onAttach 和 onCreate 方法。
  2. Activity 的 onStart 方法被调用,触发 Fragment 的 onStart 方法。
  3. Activity 的 onResume 方法被调用,触发 Fragment 的 onResume 方法。
  4. 当关闭 Activity 时,Activity 的 onPause 方法被调用,触发 Fragment 的 onPause 方法。
  5. Activity 的 onStop 方法被调用,触发 Fragment 的 onStop 方法。
  6. Activity 的 onDestroy 方法被调用,触发 Fragment 的 onDestroyViewonDestroy 和 onDetach 方法。

5.2 屏幕旋转

当屏幕旋转时,Activity 会被销毁并重新创建。在这个过程中,Fragment 的生命周期会受到影响。为了避免 Fragment 被重复创建,可以使用 setRetainInstance(true) 方法。以下是相关源码分析:

// 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 方法相关代码:

// 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 开发中这两个重要组件的使用。