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

一、整体概述

在 Android 开发中,FragmentActivity 是构建用户界面的关键组件。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 通过一系列方法调用,依次触发 ActivityonCreateonStart 等生命周期方法。

2.3 Instrumentation 对 Activity 生命周期的监控

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

scss 复制代码
// Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.onCreate(icicle);
    postPerformCreate(activity);
}

InstrumentationActivity 生命周期方法调用前后添加了一些预处理和后处理逻辑,确保 Activity 生命周期的正常执行。

三、Fragment 生命周期基础回顾

3.1 Fragment 生命周期方法概述

Fragment 的生命周期与 Activity 有相似之处,也有独特方法。主要方法如下:

  • onAttach(Context context)FragmentActivity 关联时调用。
  • onCreate(Bundle savedInstanceState)Fragment 被创建时调用,用于初始化数据。
  • onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState):创建 Fragment 的视图时调用,返回 View 对象。
  • onViewCreated(View view, Bundle savedInstanceState)Fragment 的视图创建完成后调用,可用于初始化视图组件。
  • onActivityCreated(Bundle savedInstanceState):关联的 ActivityonCreate 方法执行完成后调用。
  • onStart()Fragment 即将可见时调用。
  • onResume()Fragment 获得焦点并开始与用户交互时调用。
  • onPause()Fragment 失去焦点但仍可见时调用。
  • onStop()Fragment 不再可见时调用。
  • onDestroyView()Fragment 的视图被销毁时调用。
  • onDestroy()Fragment 即将被销毁时调用。
  • onDetach()FragmentActivity 解除关联时调用。

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 启动时,ActivityonCreate 方法会被调用。在 onCreate 方法中,会涉及到 Fragment 的恢复和创建操作。以下是 ActivityonCreate 方法相关代码:

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 关联

FragmentManagerdispatchCreate 方法中,会调用 FragmentperformCreate 方法:

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 方法中,会调用 FragmentonCreate 方法,同时将 Fragment 的状态设置为 CREATED。此时,FragmentActivity 建立了初步关联。

4.2 视图创建阶段

4.2.1 Activity 视图创建时触发 Fragment 视图创建

Activity 的视图创建过程中,FragmentManager 会根据 Fragment 的状态来决定是否创建 Fragment 的视图。当 Fragment 的状态从 CREATED 转变为 ACTIVITY_CREATED 时,会触发视图创建。以下是 FragmentManagermoveToState 方法相关代码:

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 方法:调用 FragmentonCreateView 方法,创建 Fragment 的视图。
  • onViewCreated 方法:在视图创建完成后调用,可用于初始化视图组件。

4.2.2 Fragment 视图与 Activity 视图的关联

Fragment 的视图创建完成后,会被添加到 Activity 的视图层次结构中。在 FragmentManager 中,会通过 FragmentContainer 来管理 Fragment 视图的添加和移除。具体的添加逻辑在 FragmentManageraddFragment 方法中实现:

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。例如,当 ActivityonStart 方法被调用时,会调用 FragmentManagerdispatchStart 方法

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,并调用 FragmentonStart 方法。

4.3.2 Fragment 可见性状态同步

同样,当 ActivityonResumeonPauseonStop 方法被调用时,会分别调用 FragmentManagerdispatchResumedispatchPausedispatchStop 方法,实现 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 销毁

ActivityonDestroy 方法被调用时,会调用 FragmentManagerdispatchDestroy 方法:

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,并依次调用 FragmentonDestroyViewonDestroyonDetach 方法。

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 方法中,会解除 FragmentActivity 的关联:

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

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

5.1 正常启动和关闭 Activity

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

  1. ActivityonCreate 方法被调用,触发 FragmentonAttachonCreate 方法。
  2. ActivityonStart 方法被调用,触发 FragmentonStart 方法。
  3. ActivityonResume 方法被调用,触发 FragmentonResume 方法。
  4. 当关闭 Activity 时,ActivityonPause 方法被调用,触发 FragmentonPause 方法。
  5. ActivityonStop 方法被调用,触发 FragmentonStop 方法。
  6. ActivityonDestroy 方法被调用,触发 FragmentonDestroyViewonDestroyonDetach 方法。

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;
            // ...
        }
    }
    // ...
}

mRetainInstancetrue 时,FragmentActivity 销毁时不会被销毁,而是会保留其状态,在 Activity 重新创建时直接恢复。

5.3 低内存情况

在低内存情况下,系统可能会销毁一些不常用的 ActivityFragment 以释放内存。当 Activity 被销毁时,会触发 Fragment 的销毁过程。系统会调用 ActivityonSaveInstanceState 方法保存 ActivityFragment 的状态,当 Activity 重新创建时,会从保存的状态中恢复 Fragment。以下是 ActivityonSaveInstanceState 方法相关代码:

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 重新创建时恢复。

六、总结

通过对 ActivityFragment 生命周期源码的深入分析,我们可以看到它们之间的生命周期关系是紧密相连的。Activity 作为 Fragment 的容器,通过 FragmentManager 管理 Fragment 的生命周期。在 Activity 的不同生命周期阶段,会触发 Fragment 相应的生命周期方法,实现 FragmentActivity 的协同工作。开发者在使用 Fragment 时,需要深入理解这种生命周期关系,确保在合适的时机进行资源的分配和释放,避免内存泄漏和性能问题。同时,对于不同的场景(如屏幕旋转、低内存情况),需要根据 Fragment 的特性进行合理的处理,以提供更好的用户体验。

以上内容从源码层面详细阐述了 ActivityFragment 生命周期的关系,希望能帮助开发者更好地掌握 Android 开发中这两个重要组件的使用。

相关推荐
_一条咸鱼_24 分钟前
Android Glide 缓存模块源码深度解析
android
harry235day30 分钟前
kotlin 协程创建启动 源码初探(一)
android·kotlin
fivestar20092 小时前
android studio中看错误问题
android·ide·android studio
小林熬夜学编程3 小时前
【MySQL】第十五弹---全面解析事务:定义、起源、版本支持与提交方式
android·linux·服务器·开发语言·数据库·mysql
&有梦想的咸鱼&3 小时前
Android Glide 缓存模块源码深度解析
android·缓存·glide
Gracker3 小时前
Android Weekly #202510
android·android studio
张风捷特烈3 小时前
Trae&Flutter | 助力 TolyUI 模块管理与发布
android·flutter·trae
恋猫de小郭4 小时前
再聊 Flutter Riverpod ,注解模式下的 Riverpod 有什么特别之处,还有发展方向
android·前端·flutter
*星星之火*8 小时前
【GPT入门】第5课 思维链的提出与案例
android·gpt
EasyCVR8 小时前
EasyRTC嵌入式视频通话SDK的跨平台适配,构建web浏览器、Linux、ARM、安卓等终端的低延迟音视频通信
android·arm开发·网络协议·tcp/ip·音视频·webrtc