Android 大厂面试秘籍:Activity 生命周期原理详解

深入解析 Android Activity 生命周期管理模块:源码级探秘与实践洞察

本人掘金号,欢迎点击关注:掘金号地址

本人公众号,欢迎点击关注:公众号地址

一、引言

在 Android 应用开发的广袤天地中,Activity 无疑是构建用户交互体验的核心基石。而 Activity 生命周期管理模块,作为掌控 Activity 从诞生、运行到消亡全过程的 "幕后大脑",其重要性不言而喻。无论是确保应用的流畅运行、数据的正确保存与恢复,还是优化资源利用,都与 Activity 生命周期管理紧密相连。

深入理解这一模块,不仅能让开发者在日常开发中精准把握 Activity 的状态变化,妥善处理各类业务逻辑,更是应对复杂应用场景、解决疑难问题的关键。从面试的角度看,对 Activity 生命周期管理的深刻认知也是展示开发者技术功底的重要方面。本文将深入到 Android 源码层面,全面剖析 Activity 生命周期管理模块的运行机制,通过丰富的代码示例与详尽的注释,揭开其神秘面纱,为开发者提供深入且实用的技术指引。

二、Activity 生命周期基础概念

2.1 生命周期状态概述

Activity 如同一个有生命的个体,拥有多种状态,这些状态构成了其完整的生命周期。主要状态包括:

  • 创建(Created) :Activity 首次被创建,此时系统会为其分配必要的资源,如内存空间等。
  • 启动(Started) :Activity 进入可见状态,但尚未获得焦点,用户此时还无法与之交互。
  • 恢复(Resumed) :Activity 获得焦点,处于前台运行状态,可响应用户的交互操作。
  • 暂停(Paused) :Activity 失去焦点,但部分可见,通常在此时会保存一些关键数据,释放部分资源。
  • 停止(Stopped) :Activity 完全不可见,此时可能会进一步释放资源,但其状态依然被系统保留。
  • 销毁(Destroyed) :Activity 被彻底销毁,所有资源被回收,生命周期结束。

2.2 生命周期回调方法简介

Android 为开发者提供了一系列的回调方法,以便在 Activity 生命周期的不同阶段执行特定的业务逻辑。这些回调方法如同生命周期状态转变的 "挂钩",开发者可以在这些方法中进行相应的操作。

  • onCreate(Bundle savedInstanceState) :在 Activity 创建时调用,用于初始化 Activity 的基本设置,如加载布局、初始化成员变量等。

java

java 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 设置 Activity 的布局
    setContentView(R.layout.activity_main); 
    // 初始化一些成员变量
    initVariables(); 
}
  • onStart() :在 Activity 即将可见时调用,可进行一些与界面显示相关的初始化操作,但此时 Activity 尚未获得焦点。

java

java 复制代码
@Override
protected void onStart() {
    super.onStart();
    // 例如初始化一些界面元素的显示状态
    setupUIElements(); 
}
  • onResume() :Activity 获得焦点,进入前台运行时调用,可在此方法中注册监听器等与用户交互相关的操作。

java

java 复制代码
@Override
protected void onResume() {
    super.onResume();
    // 注册点击事件监听器
    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 处理点击事件的逻辑
        }
    });
}
  • onPause() :Activity 失去焦点,即将进入暂停状态时调用,应在此方法中保存重要数据,停止动画等资源消耗操作。

java

java 复制代码
@Override
protected void onPause() {
    super.onPause();
    // 保存用户输入的数据
    saveUserInput(); 
    // 停止正在运行的动画
    stopAnimation(); 
}
  • onStop() :Activity 完全不可见时调用,可进一步释放资源,如取消网络请求等。

java

java 复制代码
@Override
protected void onStop() {
    super.onStop();
    // 取消正在进行的网络请求
    cancelNetworkRequest(); 
}
  • onDestroy() :Activity 即将被销毁时调用,用于释放所有与 Activity 相关的资源,如关闭数据库连接等。

java

java 复制代码
@Override
protected void onDestroy() {
    super.onDestroy();
    // 关闭数据库连接
    closeDatabase(); 
}
  • onRestart() :Activity 从停止状态重新启动时调用,可在此方法中进行一些恢复操作,如重新加载数据。

java

java 复制代码
@Override
protected void onRestart() {
    super.onRestart();
    // 重新加载数据
    reloadData(); 
}

2.3 典型生命周期场景示例

理解了基础概念和回调方法后,通过实际场景来进一步熟悉 Activity 生命周期的流转。

  • 正常启动流程:当用户点击应用图标启动应用时,Activity 依次经历 onCreate -> onStart -> onResume 方法,从而进入前台可交互状态。
  • 切换到后台:当用户按下 Home 键或切换到其他应用时,当前 Activity 会依次调用 onPause -> onStop 方法,进入后台不可见状态。
  • 重新回到前台:若用户再次切换回该应用,Activity 会执行 onRestart -> onStart -> onResume 方法,重新回到前台可交互状态。
  • Activity 销毁:当用户关闭应用或系统因内存不足等原因回收 Activity 时,会依次调用 onPause -> onStop -> onDestroy 方法,彻底销毁 Activity。

三、Activity 生命周期管理模块的架构与核心组件

3.1 模块架构概述

Activity 生命周期管理模块并非孤立存在,它与 Android 系统的多个层面紧密协作,形成一个复杂而有序的架构体系。从宏观上看,它依赖于 Android 的进程管理、窗口管理等底层服务,同时又为上层应用开发者提供了统一的生命周期回调接口。

在 Android 系统架构中,Activity 生命周期管理模块处于应用框架层,负责协调 Activity 与系统之间的交互。它通过一系列的类和接口,实现对 Activity 生命周期状态的跟踪、调度以及与其他组件的通信。

3.2 ActivityThread 类:生命周期管理的核心执行者

ActivityThread 类在 Activity 生命周期管理中扮演着至关重要的角色,它是应用进程的主线程,负责执行 Activity 的生命周期方法。可以将其视为 Activity 生命周期的 "导演",指挥着各个阶段的演出。

java

java 复制代码
// ActivityThread 类的部分关键源码
public final class ActivityThread extends ClientTransactionHandler {
    // 应用的主线程 Looper
    static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<>(); 
    // 存储所有已启动的 Activity 的集合
    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>(); 

    // ActivityThread 的构造函数
    public ActivityThread() {
        // 初始化一些关键组件
        // 例如初始化 Looper,为线程创建消息循环
        Looper.prepareMainLooper(); 
    }

    // 启动 Activity 的核心方法
    public Activity handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // 从 ActivityClientRecord 中获取 Activity 的信息
        ActivityInfo aInfo = r.activityInfo;
        // 获取应用的上下文
        Context appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            // 使用类加载器加载 Activity 类
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, aInfo.name, r.intent);
        } catch (Exception e) {
            // 处理加载 Activity 类时可能出现的异常
        }
        try {
            // 创建 Application 对象
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            if (activity != null) {
                // 创建 Activity 的上下文
                Context appContextImpl = new ContextImpl(appContext, r.token, this,
                        new LoadedApk(r.packageInfo), r.intent.getComponent(),
                        r.activityInfo.splitName, aInfo.applicationInfo);
                appContextImpl.setOuterContext(activity);
                // 初始化 Activity
                activity.attach(appContextImpl, 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);
                // 调用 Activity 的 onCreate 方法
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                r.activity = activity;
            }
        } catch (Exception e) {
            // 处理初始化 Activity 过程中可能出现的异常
        }
        return activity;
    }
}

在上述代码中,handleLaunchActivity 方法负责启动一个 Activity。它首先从 ActivityClientRecord 中获取 Activity 的相关信息,然后使用类加载器加载 Activity 类,并创建 Activity 的实例。接着,创建 Application 对象和 Activity 的上下文,完成 Activity 的初始化工作,并最终调用 Activity 的 onCreate 方法,正式开启 Activity 的生命周期。

3.3 ActivityStackSupervisor 类:Activity 栈的管理者

ActivityStackSupervisor 类主要负责管理 Activity 栈,Activity 栈是存储 Activity 实例的一种数据结构,它按照后进先出(LIFO)的原则管理 Activity 的显示顺序。通过 ActivityStackSupervisor,系统能够有条不紊地控制 Activity 的启动、暂停、停止和销毁等操作,确保用户界面的正确切换和管理。

java

java 复制代码
// ActivityStackSupervisor 类的部分关键源码
public class ActivityStackSupervisor {
    // 存储所有 ActivityStack 的集合
    final ArrayList<ActivityStack> mStacks = new ArrayList<>(); 
    // 系统的 ActivityManagerService 引用
    final ActivityManagerService mService; 

    // ActivityStackSupervisor 的构造函数
    public ActivityStackSupervisor(ActivityManagerService service) {
        mService = service;
        // 初始化默认的 ActivityStack
        ActivityStack stack = new ActivityStack(this, "default",
                ActivityStack.TYPE_FULLSCREEN, null);
        mStacks.add(stack);
    }

    // 将一个 Activity 压入 Activity 栈的方法
    void startActivityMayWait(IBinder callingToken, int callingUid,
                              String callingPackage, Intent intent, String resolvedType,
                              IBinder resultTo, String resultWho, int requestCode,
                              int startFlags, ProfilerInfo profilerInfo,
                              Bundle bOptions, boolean ignoreTargetSecurity, int userId,
                              IActivityManager.WaitResult outResult) {
        // 获取当前用户的 ActivityStack
        ActivityStack stack = getFocusedStack();
        // 启动 Activity 的具体逻辑
        stack.startActivityLocked(callingToken, callingUid, callingPackage, intent,
                resolvedType, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, bOptions, ignoreTargetSecurity, userId, outResult);
    }

    // 获取当前处于焦点的 ActivityStack 的方法
    ActivityStack getFocusedStack() {
        for (int i = mStacks.size() - 1; i >= 0; i--) {
            ActivityStack stack = mStacks.get(i);
            if (stack.isFocusable()) {
                return stack;
            }
        }
        return null;
    }
}

startActivityMayWait 方法中,首先获取当前用户的 ActivityStack,然后调用该 ActivityStack 的 startActivityLocked 方法将新的 Activity 压入栈中。而 getFocusedStack 方法则用于获取当前处于焦点的 ActivityStack,这在处理 Activity 的显示和交互时起着关键作用。通过 ActivityStackSupervisor 对 Activity 栈的有效管理,保证了 Activity 生命周期状态的正确切换和用户体验的流畅性。

3.4 其他相关组件及作用

除了 ActivityThread 和 ActivityStackSupervisor 这两个核心组件外,还有一些其他组件在 Activity 生命周期管理中发挥着重要作用。

  • ActivityManagerService(AMS) :作为 Android 系统中负责管理 Activity 的核心服务,它与 Activity 生命周期管理模块紧密协作。AMS 负责调度系统资源,决定何时启动、停止或销毁 Activity。它接收来自用户操作、系统事件等的指令,并通过与 ActivityStackSupervisor 等组件的交互,实现对 Activity 生命周期的宏观控制。例如,当用户启动一个新的 Activity 时,AMS 会协调 ActivityStackSupervisor 将新 Activity 压入 Activity 栈,并通知 ActivityThread 执行相应的启动流程。
  • Instrumentation 类 :Instrumentation 类为开发者提供了一种在应用运行时监控和控制 Activity 生命周期的方式。它在 Activity 的创建、启动、暂停、停止等过程中都有参与。例如,在 Activity 的创建过程中,ActivityThread 通过 Instrumentation 来调用 Activity 的 onCreate 等方法,从而实现对 Activity 生命周期的精确控制。开发者也可以通过自定义 Instrumentation 来实现一些特殊的测试或监控功能。

四、Activity 生命周期各阶段的源码剖析

4.1 onCreate 阶段

4.1.1 关键源码流程分析

当 Activity 进入 onCreate 阶段时,ActivityThread 的 handleLaunchActivity 方法起着关键作用。

java

java 复制代码
public Activity handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 从 ActivityClientRecord 中获取 Activity 的信息
    ActivityInfo aInfo = r.activityInfo;
    // 获取应用的上下文
    Context appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        // 使用类加载器加载 Activity 类
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, aInfo.name, r.intent);
    } catch (Exception e) {
        // 处理加载 Activity 类时可能出现的异常
    }
    try {
        // 创建 Application 对象
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        if (activity != null) {
            // 创建 Activity 的上下文
            Context appContextImpl = new ContextImpl(appContext, r.token, this,
                    new LoadedApk(r.packageInfo), r.intent.getComponent(),
                    r.activityInfo.splitName, aInfo.applicationInfo);
            appContextImpl.setOuterContext(activity);
            // 初始化 Activity
            activity.attach(appContextImpl, 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);
            // 调用 Activity 的 onCreate 方法
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            r.activity = activity;
        }
    } catch (Exception e) {
        // 处理初始化 Activity 过程中可能出现的异常
    }
    return activity;
}

首先,从 ActivityClientRecord 中提取 Activity 的相关信息,包括 Activity 的类名等。然后,通过类加载器加载 Activity 类并创建其实例。接着,创建 Application 对象和 Activity 的上下文环境。在完成这些准备工作后,调用 mInstrumentation.callActivityOnCreate 方法,正式触发 Activity 的 onCreate 回调。

4.1.2 与其他组件的交互

在 onCreate 阶段,Activity 与多个组件进行交互。与 Application 的交互体现在创建 Application 对象并将其与 Activity 关联,使得 Activity 可以访问应用级别的资源和状态。同时,通过 Instrumentation 来调用 onCreate 方法,Instrumentation 在这里起到了桥梁的作用,它负责协调 Activity 与系统之间的初始化流程。例如,在创建 Activity 的上下文时,会涉及到 ContextImpl 等类的交互,这些交互确保了 Activity 在正确的环境中进行初始化,包括设置 Activity 的各种属性、关联窗口等操作。

4.2 onStart 阶段

4.2.1 源码调用路径

当 Activity 进入 onStart 阶段时,ActivityThread 中的 handleStartActivity 方法开始发挥作用。

java

java 复制代码
public void handleStartActivity(ActivityClientRecord r) {
    Activity a = r.activity;
    if (a != null) {
        // 确保 Activity 处于正确的状态
        a.mStartedActivity = false;
        int enteredState = a.mState;
        int nextState = Activity.RESUMED;
        if (enteredState <= Activity.STARTED) {
            // 调用 Activity 的 onStart 方法
            mInstrumentation.callActivityOnStart(a);
            a.mState = Activity.STARTED;
        }
        if (nextState > enteredState) {
            // 调度 Activity 进入下一个状态(通常是 onResume)
            scheduleResumeActivity(r.token, false, r.isForward);
        }
    }
}

在该方法中,首先检查 Activity 的状态,若 Activity 处于合适的状态(enteredState <= Activity.STARTED),则通过 Instrumentation 调用 Activity 的 onStart 方法,将 Activity 的状态更新为 STARTED。接着,根据 Activity 的目标状态(通常是 RESUMED),调度 Activity 进入下一个状态。

4.2.2 状态更新与通知机制

在 onStart 阶段,Activity 的状态从尚未启动转变为已经启动但未恢复(未获得焦点)。这种状态的更新不仅仅是 Activity 自身状态变量的改变,还会通过系统的通知机制告知其他相关组件。例如,ActivityStackSupervisor 会根据 Activity 的状态变化来

在 onStart 阶段,Activity 的状态从尚未启动转变为已经启动但未恢复(未获得焦点)。这种状态的更新不仅仅是 Activity 自身状态变量的改变,还会通过系统的通知机制告知其他相关组件。例如,ActivityStackSupervisor 会根据 Activity 的状态变化来调整 Activity 栈的显示逻辑。当一个 Activity 进入 onStart 状态后,ActivityStackSupervisor 会确保该 Activity 处于合适的显示层级,以便在后续的流程中能够正确地进行界面展示和交互处理。

同时,这种状态变化也会影响到应用内的其他组件。比如,一些依赖于 Activity 可见性的功能模块,如某些需要在 Activity 可见时进行初始化或重新加载数据的视图组件,会接收到 Activity 进入 onStart 状态的通知,从而触发相应的操作。这种通知机制通过 Android 系统的事件分发机制来实现,确保各个组件能够及时响应 Activity 生命周期的变化,协同工作以提供一致的用户体验。

4.3 onResume 阶段

4.3.1 核心源码解读

当 Activity 进入 onResume 阶段,ActivityThread 的 handleResumeActivity 方法是关键的执行入口。

java

java 复制代码
public void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
    ActivityClientRecord r = mActivities.get(token);
    if (r != null) {
        Activity a = r.activity;
        if (a != null) {
            if (!r.activity.mFinished) {
                // 调用 Activity 的 onResume 方法
                a.performResume();
                r.activity.mResumed = true;
                if (r.window == null &&!a.mFinished && willBeVisible) {
                    r.window = r.activity.getWindow();
                    View decor = r.window.getDecorView();
                    decor.setVisibility(View.INVISIBLE);
                    ViewManager wm = a.getWindowManager();
                    WindowManager.LayoutParams l = r.window.getAttributes();
                    a.mDecor = decor;
                    l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                    l.softInputMode |= forwardBit;
                    if (a.mVisibleFromClient) {
                        a.mWindowAdded = true;
                        wm.addView(decor, l);
                    }
                }
                // 调度执行 Activity 的 postResume 操作
                r.pendingIntents = null;
                sendActivityResult(r, a, false);
                if (r.isForward) {
                    if (r.activity.mVisibleFromClient) {
                        r.activity.makeVisible();
                    }
                } else {
                    if (r.hideForNow) {
                        a.hide();
                        r.hideForNow = false;
                    } else {
                        if (r.activity.mVisibleFromClient) {
                            r.activity.makeVisible();
                        }
                    }
                }
            }
        }
    }
}

在此方法中,首先获取对应的 ActivityClientRecord 和 Activity 实例。若 Activity 尚未完成(!r.activity.mFinished),则调用 Activity 的 performResume 方法,该方法内部会触发 Activity 的 onResume 回调。接着,对 Activity 的窗口进行一系列的初始化和显示相关操作,包括获取窗口、设置窗口属性、添加视图到窗口管理器等。最后,根据不同的条件(如是否是向前导航、是否隐藏等),决定是否显示 Activity。

4.3.2 窗口与视图相关操作

在 onResume 阶段,与窗口和视图相关的操作十分关键。Activity 的窗口(Window)是用户与 Activity 交互的载体,在 onResume 时,会对窗口进行一系列的配置和显示操作。例如,获取窗口的装饰视图(DecorView),设置其初始可见性为不可见(decor.setVisibility(View.INVISIBLE)),然后根据 Activity 的可见性条件(a.mVisibleFromClient),通过窗口管理器(WindowManager)将装饰视图添加到窗口中(wm.addView(decor, l)),并最终根据不同情况决定是否让 Activity 真正可见(r.activity.makeVisible())。

这些操作确保了 Activity 的界面能够正确地展示在用户面前,并且能够响应用户的交互。同时,视图相关的初始化和配置也会在这个阶段完成,例如,之前在 onCreate 或 onStart 中初始化的视图组件,在 onResume 阶段会完成最后的布局调整和事件监听器注册等操作,使得视图能够正常工作,为用户提供交互功能。

4.4 onPause 阶段

4.4.1 源码中的暂停逻辑

当 Activity 进入 onPause 阶段,ActivityThread 的 handlePauseActivity 方法负责处理相关逻辑。

java

java 复制代码
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) {
    ActivityClientRecord r = mActivities.get(token);
    if (r != null) {
        Activity a = r.activity;
        if (a != null) {
            if (userLeaving) {
                a.mUserLeaving = true;
            }
            // 调用 Activity 的 onPause 方法
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
            if (finished) {
                if (r.isPreHoneycomb()) {
                    r.setState(ActivityState.PAUSED);
                } else {
                    r.setState(ActivityState.STOPPED);
                }
            }
            if (r.pendingResults!= null) {
                // 处理挂起的结果
                for (int i = 0; i < r.pendingResults.size(); i++) {
                    deliverResults(r, r.pendingResults.get(i));
                }
                r.pendingResults = null;
            }
            if (r.pendingIntents!= null) {
                // 处理挂起的意图
                for (int i = 0; i < r.pendingIntents.size(); i++) {
                    sendPendingIntent(r, r.pendingIntents.get(i));
                }
                r.pendingIntents = null;
            }
        }
    }
}

该方法首先获取对应的 Activity 记录和 Activity 实例。如果用户正在离开该 Activity(userLeaving 为 true),则设置 Activity 的 mUserLeaving 标志位。然后,调用 performPauseActivity 方法,在该方法内部会触发 Activity 的 onPause 回调。如果 Activity 即将完成(finished 为 true),则根据 Android 版本(是否是 pre - Honeycomb)设置 Activity 的状态。最后,处理 Activity 中挂起的结果(pendingResults)和意图(pendingIntents)。

4.4.2 数据保存与资源释放

在 onPause 阶段,一个重要的任务是保存数据和释放部分资源。从数据保存角度来看,开发者通常会在 Activity 的 onPause 方法中保存用户当前的输入数据、界面状态等重要信息。例如,对于一个文本输入框,在 onPause 时可以将用户输入的文本保存起来,以便在 Activity 恢复时能够恢复到之前的状态。

java

java 复制代码
@Override
protected void onPause() {
    super.onPause();
    EditText editText = findViewById(R.id.edit_text);
    String inputText = editText.getText().toString();
    // 假设这里有一个方法用于保存输入文本
    saveInputText(inputText);
}

在资源释放方面,一些正在运行且在 Activity 暂停期间不需要的资源,如动画、网络请求等,需要及时停止或取消。比如,正在播放的动画会消耗系统资源,在 onPause 时应该停止动画播放。

java

java 复制代码
@Override
protected void onPause() {
    super.onPause();
    Animation animation = findViewById(R.id.anim_view).getAnimation();
    if (animation!= null) {
        animation.cancel();
    }
}

这样可以避免资源的浪费,提高系统资源的利用效率,同时也能确保在 Activity 恢复时能够正确地重新初始化资源,保证应用的正常运行。

4.5 onStop 阶段

4.5.1 停止过程的源码解析

当 Activity 进入 onStop 阶段,ActivityThread 的 handleStopActivity 方法主导相关流程。

java

java 复制代码
public void handleStopActivity(IBinder token, boolean show, int configChanges, boolean getNonConfigInstance, boolean report) {
    ActivityClientRecord r = mActivities.get(token);
    if (r!= null) {
        Activity a = r.activity;
        if (a!= null) {
            if (!getNonConfigInstance) {
                // 调用 Activity 的 onStop 方法
                mInstrumentation.callActivityOnStop(a);
                a.mStopped = true;
            }
            if (report) {
                try {
                    // 向 ActivityManagerService 报告 Activity 已停止
                    mService.activityStopped(r.token);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            if (show) {
                // 处理 Activity 停止时的显示相关操作(通常为空实现)
                handleStopActivityInner(r, getNonConfigInstance);
            }
        }
    }
}

此方法首先获取对应的 Activity 记录和 Activity 实例。若不需要获取非配置实例(!getNonConfigInstance),则通过 Instrumentation 调用 Activity 的 onStop 方法,并设置 Activity 的 mStopped 标志位。接着,如果需要报告(report 为 true),则向 ActivityManagerService 报告 Activity 已停止,这有助于系统对 Activity 的状态进行全局管理。如果有显示相关的特殊需求(show 为 true),则调用 handleStopActivityInner 方法进行处理,但通常这个方法在默认情况下为空实现。

4.5.2 资源释放与内存优化

在 onStop 阶段,进一步的资源释放和内存优化工作至关重要。此时,Activity 已经完全不可见,系统可以释放更多的资源以优化内存使用。例如,对于一些占用较大内存的对象,如加载的大图片、缓存数据等,如果在 Activity 停止期间不再需要,可以在 onStop 方法中进行释放。

java

java 复制代码
@Override
protected void onStop() {
    super.onStop();
    Bitmap largeBitmap = (Bitmap) getLastNonConfigurationInstance();
    if (largeBitmap!= null &&!largeBitmap.isRecycled()) {
        largeBitmap.recycle();
    }
    // 假设这里有一个缓存数据的清理方法
    clearCacheData();
}

此外,一些与 Activity 相关的后台任务,如果在 Activity 停止后不需要继续运行,也应该在此阶段停止。比如,一个在后台持续运行的定时器任务,在 onStop 时可以取消该定时器,避免不必要的资源消耗。

java

java 复制代码
@Override
protected void onStop() {
    super.onStop();
    if (timer!= null) {
        timer.cancel();
        timer = null;
    }
}

通过这些操作,不仅可以提高应用自身的性能,还能为系统中其他正在运行的应用或服务释放更多的内存资源,提升整个系统的运行效率。

4.6 onDestroy 阶段

4.6.1 销毁操作的源码执行

当 Activity 进入 onDestroy 阶段,ActivityThread 的 handleDestroyActivity 方法负责处理销毁逻辑。

java

java 复制代码
public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) {
    ActivityClientRecord r = mActivities.get(token);
    if (r!= null) {
        Activity a = r.activity;
        if (a!= null) {
            if (getNonConfigInstance) {
                try {
                    // 获取非配置实例(用于配置变更等情况)
                    Object lastNonConfigurationInstances = a.retainNonConfigurationInstances();
                    r.lastNonConfigurationInstances = lastNonConfigurationInstances;
                } catch (Exception e) {
                    if (!mInstrumentation.onException(a, e)) {
                        throw new RuntimeException("Unable to retain activity "
                                + a.getComponentName().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
            }
            if (finishing) {
                // 调用 Activity 的 onDestroy 方法
                mInstrumentation.callActivityOnDestroy(a);
            }
            a.mFinished = true;
            // 从 Activity 记录集合中移除该 Activity 记录
            mActivities.remove(token);
            try {
                // 通知 ActivityManagerService Activity 已销毁
                mService.activityDestroyed(token);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
}

该方法首先获取对应的 Activity 记录和 Activity 实例。如果需要获取非配置实例(getNonConfigInstance 为 true),则调用 Activity 的 retainNonConfigurationInstances 方法获取相关实例。若 Activity 正在完成(finishing 为 true),则通过 Instrumentation 调用 Activity 的 onDestroy 方法。然后,设置 Activity 的 mFinished 标志位,并从 Activity 记录集合中移除该 Activity 记录。最后,通知 ActivityManagerService Activity 已销毁,完成 Activity 的整个销毁流程。

4.6.2 彻底资源清理与对象回收

在 onDestroy 阶段,Activity 即将被彻底销毁,此时需要进行最彻底的资源清理和对象回收工作。所有与 Activity 相关的资源,包括但不限于数据库连接、文件句柄、网络连接等,都应该在此阶段关闭或释放。例如,关闭数据库连接以避免资源泄漏。

java

java 复制代码
@Override
protected void onDestroy() {
    super.onDestroy();
    SQLiteDatabase db = getDatabase();
    if (db!= null && db.isOpen()) {
        db.close();
    }
}

对于自定义的对象和资源,也需要进行清理。比如,一个在 Activity 中创建并管理的对象池,在 onDestroy 时需要释放对象池中的所有对象。

java

java 复制代码
@Override
protected void onDestroy() {
    super.onDestroy();
    ObjectPool objectPool = getObjectPool();
    if (objectPool!= null) {
        objectPool.releaseAllObjects();
    }
}

此外,对于在 Activity 中注册的各种监听器,也应该在此阶段移除,防止内存泄漏。例如,移除注册的广播接收器。

java

java 复制代码
@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(broadcastReceiver);
}

通过这些全面而彻底的资源清理和对象回收操作,确保 Activity 在销毁后不会留下任何未释放的资源,保证系统资源的干净和高效利用。

4.7 onRestart 阶段

4.7.1 重启流程的源码剖析

当 Activity 进入 onRestart 阶段,ActivityThread 的 handleRestartActivity 方法开始发挥作用。

java

java 复制代码
public void handleRestartActivity(IBinder token) {
    ActivityClientRecord r = mActivities.get(token);
    if (r!= null) {
        Activity a = r.activity;
        if (a!= null) {
            if (!a.mFinished) {
                try {
                    // 调用 Activity 的 onRestart 方法
                    mInstrumentation.callActivityOnRestart(a);
                } catch (Exception e) {
                    if (!mInstrumentation.onException(a, e)) {
                        throw new RuntimeException("Unable to restart activity "
                                + a.getComponentName().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                // 调度 Activity 进入 onStart 阶段
                handleStartActivity(r);
            }
        }
    }
}

此方法首先获取对应的 Activity 记录和 Activity 实例。若 Activity 尚未完成(!a.mFinished),则通过 Instrumentation 调用 Activity 的 onRestart 方法。在 onRestart 方法执行完毕后,接着调用 handleStartActivity 方法,将 Activity 带入 onStart 阶段,从而开始新一轮的生命周期流程,使得 Activity 重新可见并进入可交互状态。

4.7.2 恢复数据与重新初始化

在 onRestart 阶段,一个重要的任务是恢复数据和重新初始化相关资源。当 Activity 从停止状态重新启动时,可能需要恢复之前保存的数据,以及重新初始化一些在停止期间被释放或需要重新设置的资源。例如,恢复之前保存的用户界面状态数据。

java

java 复制代码
@Override
protected void onRestart() {
    super.onRestart();
    // 假设这里有一个方法用于获取之前保存的界面状态数据
    Bundle savedState = getSavedState();
    if (savedState!= null) {
        // 根据保存的状态数据恢复界面
        restoreUIState(savedState);
    }
}

同时,对于一些在停止期间停止的服务或功能,需要重新初始化。比如,重新初始化一个在 onStop 时暂停的传感器监听服务。

java

java 复制代码
@Override
protected void onRestart() {
    super.onRestart();
    SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}

通过这些恢复数据和重新初始化的操作,确保 Activity 在重新启动后能够恢复到之前的状态,并正常提供各种功能,为用户提供连贯的使用体验。

五、特殊场景下的 Activity 生命周期管理

5.1 配置变更(如屏幕旋转)

5.1.1 配置变更时的生命周期变化

当发生配置变更,如屏幕旋转时,Activity 的生命周期会经历一系列的变化。默认情况下,Android 系统会销毁当前的 Activity 实例,然后重新创建一个新的实例。具体的生命周期回调顺序为:onPause -> onStop -> onDestroy -> onCreate -> onStart -> onResume

onDestroy 之前,系统会调用 onSaveInstanceState 方法,允许开发者保存 Activity 的当前状态。而在新的 Activity 实例创建后的 onCreate 方法中,开发者可以通过传入的 Bundle 参数获取之前保存的状态。以下是一个简单的示例代码:

java

java 复制代码
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    // 保存一些重要的数据,例如用户输入的文本
    EditText editText = findViewById(R.id.edit_text);
    String inputText = editText.getText().toString();
    outState.putString("input_text", inputText);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState != null) {
        // 恢复之前保存的数据
        String inputText = savedInstanceState.getString("input_text");
        EditText editText = findViewById(R.id.edit_text);
        editText.setText(inputText);
    }
}
5.1.2 避免 Activity 重建的方法

为了避免在配置变更时 Activity 被销毁和重建带来的性能开销和数据丢失问题,开发者可以通过在 AndroidManifest.xml 中为 Activity 添加 android:configChanges 属性来处理。例如:

xml

java 复制代码
<activity
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize">
    ...
</activity>

当设置了 android:configChanges 属性后,在配置变更时,系统不会销毁和重建 Activity,而是调用 Activity 的 onConfigurationChanged 方法。开发者可以在该方法中手动处理配置变更带来的影响。以下是 onConfigurationChanged 方法的示例代码:

java

java 复制代码
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // 检查屏幕方向的变化
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        // 处理横屏模式下的布局调整
        adjustLayoutForLandscape();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        // 处理竖屏模式下的布局调整
        adjustLayoutForPortrait();
    }
}

private void adjustLayoutForLandscape() {
    // 调整布局,例如重新排列视图组件
    LinearLayout layout = findViewById(R.id.main_layout);
    layout.setOrientation(LinearLayout.HORIZONTAL);
}

private void adjustLayoutForPortrait() {
    // 调整布局,例如重新排列视图组件
    LinearLayout layout = findViewById(R.id.main_layout);
    layout.setOrientation(LinearLayout.VERTICAL);
}

5.2 多 Activity 交互场景

5.2.1 启动新 Activity 时的生命周期影响

当一个 Activity 启动另一个 Activity 时,两个 Activity 的生命周期都会受到影响。假设当前 Activity 为 ActivityA,启动的新 Activity 为 ActivityB。当 ActivityA 调用 startActivity(intent) 启动 ActivityB 时,ActivityA 会依次调用 onPause 方法,然后 ActivityB 会经历 onCreate -> onStart -> onResume 方法,进入前台可见状态。此时,ActivityA 进入后台,可能会接着调用 onStop 方法,具体取决于 ActivityB 是否完全覆盖 ActivityA

以下是一个简单的代码示例,展示了 ActivityA 启动 ActivityB 的过程:

java

java 复制代码
// ActivityA 中的启动代码
public class ActivityA extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);

        Button startButton = findViewById(R.id.start_button);
        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(ActivityA.this, ActivityB.class);
                startActivity(intent);
            }
        });
    }
}

// ActivityB 的代码
public class ActivityB extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);
    }
}
5.2.2 返回栈管理与生命周期协同

在多 Activity 交互场景中,Android 系统使用返回栈(Back Stack)来管理 Activity 的顺序。每个 Activity 启动时会被压入返回栈,当用户按下返回键时,栈顶的 Activity 会被弹出并销毁,下面的 Activity 会重新回到前台。

返回栈的管理与 Activity 的生命周期密切相关。当一个新的 Activity 被压入返回栈时,栈顶的 Activity 会暂停并可能停止;当栈顶的 Activity 被弹出时,下面的 Activity 会恢复并重新进入前台。开发者可以通过 Intent 的启动模式(如 standardsingleTopsingleTasksingleInstance)来控制 Activity 在返回栈中的行为。

例如,使用 singleTask 启动模式可以确保一个 Activity 在返回栈中只有一个实例。当启动一个以 singleTask 模式启动的 Activity 时,如果该 Activity 已经存在于返回栈中,系统会将该 Activity 之上的所有 Activity 弹出,使其成为栈顶 Activity 并恢复。以下是在 AndroidManifest.xml 中设置 singleTask 启动模式的示例:

xml

java 复制代码
<activity
    android:name=".MainActivity"
    android:launchMode="singleTask">
    ...
</activity>

5.3 系统资源不足时的 Activity 回收

5.3.1 系统回收策略与生命周期关联

当系统资源(如内存)不足时,Android 系统会根据一定的策略回收 Activity 以释放资源。系统会优先回收那些处于后台且长时间未使用的 Activity。Activity 的生命周期状态会影响其被回收的优先级。一般来说,处于 onStop 状态的 Activity 比处于 onPause 状态的 Activity 更容易被回收。

系统在回收 Activity 时,会调用 Activity 的 onDestroy 方法。在回收之前,系统会调用 onSaveInstanceState 方法,允许开发者保存 Activity 的重要状态。当用户再次回到该 Activity 时,系统会重新创建该 Activity 实例,并在 onCreateonRestoreInstanceState 方法中恢复之前保存的状态。

5.3.2 开发者应对资源回收的措施

开发者可以采取一些措施来应对系统资源回收的情况。首先,在 onSaveInstanceState 方法中,要确保保存所有重要的数据,如用户输入、当前的滚动位置等。例如:

java

java 复制代码
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    // 保存当前滚动位置
    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
    int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
    outState.putInt("scroll_position", firstVisibleItemPosition);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    // 恢复滚动位置
    int scrollPosition = savedInstanceState.getInt("scroll_position");
    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
    layoutManager.scrollToPosition(scrollPosition);
}

其次,在 onDestroy 方法中,要确保释放所有不再需要的资源,如数据库连接、网络请求等,避免资源泄漏。同时,可以考虑使用一些数据缓存机制,如 ViewModel 来保存一些临时数据,在 Activity 重建时可以快速恢复。

java

java 复制代码
import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    private String importantData;

    public String getImportantData() {
        return importantData;
    }

    public void setImportantData(String data) {
        this.importantData = data;
    }
}

// 在 Activity 中使用 ViewModel
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private MyViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewModel = new ViewModelProvider(this).get(MyViewModel.class);
        if (viewModel.getImportantData() != null) {
            // 恢复数据
            displayData(viewModel.getImportantData());
        }
    }

    private void displayData(String data) {
        // 显示数据的逻辑
    }
}

六、Activity 生命周期管理的性能优化

6.1 减少不必要的生命周期回调

6.1.1 避免重复初始化

在 Activity 的生命周期方法中,要避免重复初始化一些对象或执行一些不必要的操作。例如,在 onCreate 方法中已经初始化了一个对象,就不要在 onStartonResume 方法中再次初始化。可以通过添加标志位来判断是否已经初始化过。

java

java 复制代码
private boolean isInitialized = false;
private SomeObject someObject;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (!isInitialized) {
        someObject = new SomeObject();
        isInitialized = true;
    }
}

@Override
protected void onStart() {
    super.onStart();
    // 不要在这里再次初始化 someObject
}
6.1.2 按需加载资源

对于一些资源(如图片、数据等),要按需加载,避免在 Activity 创建时就加载所有资源。可以在需要显示这些资源时再进行加载。例如,使用 Lazy 加载机制来加载图片。

java

java 复制代码
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private ImageView imageView;
    private Bitmap lazyBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.image_view);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (lazyBitmap == null) {
            // 按需加载图片
            lazyBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image);
            imageView.setImageBitmap(lazyBitmap);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (lazyBitmap != null) {
            // 在暂停时释放图片资源
            lazyBitmap.recycle();
            lazyBitmap = null;
        }
    }
}

6.2 优化数据保存与恢复流程

6.2.1 精简保存的数据

onSaveInstanceState 方法中,要尽量精简保存的数据,只保存那些真正需要恢复的数据。保存过多的数据会增加 Activity 重建时的开销。例如,对于一些临时的中间计算结果,如果在 Activity 重建后不需要恢复,就不要保存。

java

java 复制代码
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    // 只保存必要的数据
    EditText editText = findViewById(R.id.edit_text);
    String inputText = editText.getText().toString();
    outState.putString("input_text", inputText);
}
6.2.2 高效的数据恢复方式

在恢复数据时,要采用高效的方式。可以使用 Bundle 提供的 containsKey 方法来检查数据是否存在,避免不必要的空指针异常。同时,对于一些复杂的数据结构,可以考虑使用 ParcelableSerializable 接口来进行序列化和反序列化。

java

java 复制代码
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (savedInstanceState.containsKey("input_text")) {
        String inputText = savedInstanceState.getString("input_text");
        EditText editText = findViewById(R.id.edit_text);
        editText.setText(inputText);
    }
}

6.3 合理使用生命周期方法进行资源管理

6.3.1 及时释放资源

在 Activity 的生命周期方法中,要及时释放不再需要的资源。例如,在 onPauseonStop 方法中,停止正在运行的动画、取消网络请求等。

java

java 复制代码
private Animation animation;
private NetworkRequest networkRequest;

@Override
protected void onPause() {
    super.onPause();
    if (animation != null) {
        animation.cancel();
    }
    if (networkRequest != null) {
        networkRequest.cancel();
    }
}
6.3.2 避免内存泄漏

要注意避免在 Activity 的生命周期方法中造成内存泄漏。例如,在使用内部类时,要避免内部类持有外部 Activity 的强引用。可以使用静态内部类和弱引用来解决这个问题。

java

java 复制代码
import android.os.Handler;
import android.os.Message;
import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity {
    private MyHandler myHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myHandler = new MyHandler(this);
    }

    private static class MyHandler extends Handler {
        private WeakReference<MainActivity> activityWeakReference;

        public MyHandler(MainActivity activity) {
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = activityWeakReference.get();
            if (activity != null) {
                // 处理消息
            }
        }
    }
}

七、Activity 生命周期管理的常见问题与解决方案

7.1 内存泄漏问题

7.1.1 常见的内存泄漏原因

在 Activity 生命周期管理中,常见的内存泄漏原因包括:

  • 静态变量引用:如果将 Activity 或其内部的 View 赋值给静态变量,由于静态变量的生命周期与应用的生命周期相同,会导致 Activity 无法被垃圾回收。

java

java 复制代码
public class MainActivity extends AppCompatActivity {
    private static MainActivity instance;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        instance = this;
    }
}
  • 内部类持有外部 Activity 引用:非静态内部类会隐式持有外部 Activity 的引用,如果内部类的生命周期长于 Activity,会导致 Activity 无法被回收。

java

java 复制代码
public class MainActivity extends AppCompatActivity {
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // 处理消息
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler.sendEmptyMessageDelayed(0, 10000);
    }
}
  • 未注销的监听器:如果在 Activity 中注册了监听器(如广播接收器、传感器监听器等),但在 Activity 销毁时没有注销,会导致监听器持有 Activity 的引用,造成内存泄漏。

java

java 复制代码
public class MainActivity extends AppCompatActivity {
    private BroadcastReceiver broadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // 处理广播
            }
        };
        registerReceiver(broadcastReceiver, new IntentFilter("SOME_ACTION"));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 忘记注销广播接收器
    }
}
7.1.2 解决方案与预防措施

为了解决和预防内存泄漏问题,可以采取以下措施:

  • 避免静态变量引用 Activity:尽量避免将 Activity 或其内部的 View 赋值给静态变量。如果确实需要保存一些全局状态,可以考虑使用单例模式,并使用弱引用。

java

java 复制代码
import java.lang.ref.WeakReference;

public class MySingleton {
    private static MySingleton instance;
    private WeakReference<MainActivity> activityWeakReference;

    private MySingleton() {}

    public static MySingleton getInstance() {
        if (instance == null) {
            instance = new MySingleton();
        }
        return instance;
    }

    public void setActivity(MainActivity activity) {
        activityWeakReference = new WeakReference<>(activity);
    }

    public MainActivity getActivity() {
        if (activityWeakReference != null) {
            return activityWeakReference.get();
        }
        return null;
    }
}
  • 使用静态内部类和弱引用:对于内部类,使用静态内部类,并使用弱引用持有外部 Activity 的引用。

java

java 复制代码
import android.os.Handler;
import android.os.Message;
import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity {
    private MyHandler myHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myHandler = new MyHandler(this);
    }

    private static class MyHandler extends Handler {
        private WeakReference<MainActivity> activityWeakReference;

        public MyHandler(MainActivity activity) {
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = activityWeakReference.get();
            if (activity != null) {
                // 处理消息
            }
        }
    }
}
  • 及时注销监听器 :在 Activity 的 onDestroy 方法中,确保注销所有注册的监听器。

java

java 复制代码
public class MainActivity extends AppCompatActivity {
    private BroadcastReceiver broadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // 处理广播
            }
        };
        registerReceiver(broadcastReceiver, new IntentFilter("SOME_ACTION"));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(broadcastReceiver);
    }
}

7.2 数据丢失问题

7.2.1 数据丢失的场景分析

在 Activity 生命周期管理中,数据丢失问题可能出现在以下场景:

  • 配置变更:当发生配置变更(如屏幕旋转)时,如果没有正确保存和恢复数据,会导致数据丢失。例如,用户在输入框中输入的文本,在屏幕旋转后可能会丢失。
  • 系统资源回收 :当系统资源不足时,Activity 可能会被系统回收。如果没有在 onSaveInstanceState 方法中保存重要数据,这些数据会丢失。
  • 异常退出:如果 Activity 因异常(如崩溃)而退出,没有保存的数据也会丢失。
7.2.2 数据保存与恢复的最佳实践

为了避免数据丢失问题,可以采取以下最佳实践:

  • onSaveInstanceState 中保存数据 :在 onSaveInstanceState 方法中,保存所有需要恢复的数据。可以保存基本数据类型、字符串、数组等,也可以保存实现了 ParcelableSerializable 接口的对象。

java

java 复制代码
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    EditText editText = findViewById(R.id.edit_text);
    String inputText = editText.getText().toString();
    outState.putString("input_text", inputText);
}
  • onCreateonRestoreInstanceState 中恢复数据 :在 Activity 重建时,在 onCreateonRestoreInstanceState 方法中恢复之前保存的数据。

java

java 复制代码
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (savedInstanceState.containsKey("input_text")) {
        String inputText = savedInstanceState.getString("input_text");
        EditText editText = findViewById(R.id.edit_text);
        editText.setText(inputText);
    }
}
  • 使用 ViewModel 保存临时数据 :对于一些临时数据,可以使用 ViewModel 来保存。ViewModel 的生命周期与 Activity 的配置变更无关,在 Activity 重建时可以保留数据。

java

java 复制代码
import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    private String importantData;

    public String getImportantData() {
        return importantData;
    }

    public void setImportantData(String data) {
        this.importantData = data;
    }
}

// 在 Activity 中使用 ViewModel
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private MyViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewModel = new ViewModelProvider(this).get(MyViewModel.class);
        if (viewModel.getImportantData() != null) {
            // 恢复数据
            displayData(viewModel.getImportantData());
        }
    }

    private void displayData(String data) {
        // 显示数据的逻辑
    }
}

7.3 生命周期回调顺序混乱问题

7.3.1 可能导致顺序混乱的因素

生命周期回调顺序混乱可能由以下因素导致:

  • 异步操作 :如果在 Activity 的生命周期方法中执行异步操作,并且这些操作的完成时间不确定,可能会导致回调顺序混乱。例如,在 onCreate 方法中启动一个异步任务,任务的完成回调可能在 onStartonResume 方法之后才执行。
  • 多线程操作:在多线程环境下,如果多个线程同时访问和修改 Activity 的状态,可能会导致生命周期回调顺序混乱。例如,一个线程在修改 Activity 的状态,而另一个线程正在调用生命周期方法。
  • 第三方库的影响:某些第三方库可能会在 Activity 的生命周期方法中插入自己的代码,导致回调顺序混乱。
7.3.2 确保回调顺序正确的方法

为了确保生命周期回调顺序正确,可以采取以下方法:

  • 同步执行关键操作 :对于一些关键操作,尽量在主线程中同步执行,避免异步操作带来的顺序问题。例如,在 onCreate 方法中初始化一些必要的对象,确保在后续的生命周期方法中可以正常使用。

java

java 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 同步初始化对象
    myObject = new MyObject();
}
  • 使用锁机制 :在多线程环境下,使用锁机制来保证线程安全。例如,使用 synchronized 关键字来确保同一时间只有一个线程可以访问和修改 Activity 的状态。

java

java 复制代码
private Object lock = new Object();

@Override
protected void onStart() {
    super.onStart();
    synchronized (lock) {
        // 执行需要同步的操作
    }
}
  • 仔细选择第三方库 :在使用第三方库时,要仔细阅读文档,了解其对 Activity 生命周期的影响。如果可能,选择对生命周期影响较小的库。同时,可以通过自定义 Application 类来监控 Activity 的生命周期,确保第三方库不会干扰正常的回调顺序。

java

java 复制代码
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;

public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {
    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(this);
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        // 监控 Activity 创建事件
    }

    @Override
    public void onActivityStarted(Activity activity) {
        // 监控 Activity 启动事件
    }

    @Override
    public void onActivityResumed(Activity activity) {
        // 监控 Activity 恢复事件
    }

    @Override
    public void onActivityPaused(Activity activity) {
        // 监控 Activity 暂停事件
    }

    @Override
    public void onActivityStopped(Activity activity) {
        // 监控 Activity 停止事件
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        // 监控 Activity 保存状态事件
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        // 监控 Activity 销毁事件
    }
}

八、总结与展望

8.1 总结

通过对 Android Activity 生命周期管理模块的深入剖析,我们全面了解了 Activity 从创建到销毁的整个生命周期过程,以及各个阶段的关键源码实现。Activity 生命周期管理模块是 Android 应用开发中至关重要的一部分,它直接影响着应用的性能、稳定性和用户体验。

我们明确了 Activity 生命周期的基本概念和回调方法,以及这些方法在不同场景下的调用顺序和作用。从源码层面分析了 ActivityThread、ActivityStackSupervisor 等核心组件在生命周期管理中的作用,了解了它们如何协同工作,实现对 Activity 的创建、启动、暂停、停止和销毁等操作的精确控制。

同时,我们探讨了特殊场景下的 Activity 生命周期管理,如配置变更、多 Activity 交互和系统资源不足时的回收策略。针对这些场景,我们提出了相应的解决方案和最佳实践,帮助开发者更好地处理这些复杂情况,避免数据丢失和性能问题。

在性能优化方面,我们介绍了减少不必要的生命周期回调、优化数据保存与恢复流程以及合理使用生命周期方法进行资源管理等方法,这些方法可以有效提高应用的性能和响应速度。此外,我们还分析了 Activity 生命周期管理中常见的问题,如内存泄漏、数据丢失和回调顺序混乱等,并给出了相应的解决方案和预防措施。

8.2 展望

随着 Android 技术的不断发展,Activity 生命周期管理模块也将不断演进和完善。未来,我们可以期待以下几个方面的发展:

  • 更智能的生命周期管理:Android 系统可能会引入更智能的生命周期管理机制,自动根据设备的状态、资源使用情况和用户的操作习惯,动态调整 Activity 的生命周期,以提高系统资源的利用效率和应用的性能。例如,系统可以根据当前的内存使用情况,自动决定是否回收一些处于后台的 Activity,或者在设备电量较低时,优先保留一些关键的 Activity。

  • 简化开发者的工作:为了降低开发者的开发难度,未来的 Android 框架可能会提供更简洁、易用的 API 来管理 Activity 的生命周期。例如,可能会提供一些高级的注解或工具类,让开发者可以更方便地处理配置变更、数据保存与恢复等问题,减少样板代码的编写。

  • 更好的兼容性和稳定性:随着 Android 设备的多样性不断增加,Activity 生命周期管理模块需要更好地适应不同的设备和系统版本。未来的 Android 系统可能会加强对不同设备的兼容性测试,确保 Activity 在各种设备上都能正常运行,同时提高系统的稳定性,减少因生命周期管理问题导致的应用崩溃和异常。

  • 与其他组件的深度集成:Activity 作为 Android 应用的核心组件之一,未来可能会与其他组件(如 Fragment、Service、BroadcastReceiver 等)进行更深度的集成。例如,在 Activity 的生命周期管理中,可以更方便地管理 Fragment 的生命周期,实现更高效的界面切换和数据传递。

总之,Android Activity 生命周期管理模块的发展将为开发者提供更强大、更便捷的开发工具,同时也将为用户带来更流畅、更稳定的应用体验。开发者需要不断关注这些技术的发展,及时学习和掌握新的知识和技能,以适应未来 Android 开发的需求。

相关推荐
江城开朗的豌豆9 分钟前
CSS篇:前端经典布局方案:左侧固定右侧自适应的6种实现方式
前端·css·面试
_一条咸鱼_10 分钟前
大厂Android面试秘籍:Activity 布局加载与视图管理(五)
android·面试·kotlin
江城开朗的豌豆14 分钟前
CSS篇:CSS选择器详解与权重计算全指南
前端·css·面试
Aphasia31121 分钟前
一家前端远程实习公司的笔试题分享📑
前端·面试
海风极客40 分钟前
一文搞懂JSON和HJSON
前端·后端·面试
海风极客43 分钟前
一文搞懂Clickhouse的MySQL引擎
后端·面试·架构
阳树阳树1 小时前
Solidjs 响应式 & 编译原理初探
前端·javascript·面试
MurphyChen1 小时前
前端请求进化史 :从 Form 到 Server Actions 🚀
前端·javascript·面试
猿java3 小时前
你使用过 Service Mesh吗?
java·面试·service mesh