Android Activity 生命周期解析

文章目录

    • 前言
    • [1. 项目整体介绍](#1. 项目整体介绍)
      • [Activity 职责一览](#Activity 职责一览)
    • [2. Activity 生命周期概览](#2. Activity 生命周期概览)
    • [3. 源码逐行解读](#3. 源码逐行解读)
      • [3.1 MainActivity(核心)](#3.1 MainActivity(核心))
      • [3.2 NormalActivity](#3.2 NormalActivity)
      • [3.3 DialogActivity(对话框主题)](#3.3 DialogActivity(对话框主题))
      • [3.4 布局文件](#3.4 布局文件)
      • [3.5 AndroidManifest.xml](#3.5 AndroidManifest.xml)
    • [4. 五种场景下的生命周期调用顺序](#4. 五种场景下的生命周期调用顺序)
    • [5. 关键知识点深度剖析](#5. 关键知识点深度剖析)
      • [5.1 `onPause` vs `onStop` 的区别](#5.1 onPause vs onStop 的区别)
      • [5.2 `onSaveInstanceState` 的作用](#5.2 onSaveInstanceState 的作用)
      • [5.3 为什么在 `onCreate` 中恢复数据?](#5.3 为什么在 onCreate 中恢复数据?)
      • [5.4 完整生命周期状态图](#5.4 完整生命周期状态图)
    • [6. 总结](#6. 总结)

前言

对于每一位 Android 开发者来说,理解 Activity 的生命周期 是最基础也是最重要的入门知识。面试必问、开发必用、排查问题必备。

本文将借助一个Demo 项目 ------ ActivityLifeCycleTest ,通过 实际代码 + 日志验证 + 场景模拟 的方式,带你彻底搞懂 Activity 的 7 个生命周期方法和不同场景下的回调顺序。即使你是零基础的初学者,也能通过本文一步到位。


1. 项目整体介绍

项目属性 说明
项目名称 ActivityLifeCycleTest
语言 Java + XML
Activity 数量 3 个
核心机制 每个 Activity 的 7 个生命周期方法都打上了 Log 日志

Activity 职责一览

Activity 主题 作用
MainActivity 默认主题(全屏) 入口页面,两个按钮分别启动另外两个 Activity
NormalActivity 默认主题(全屏) 模拟启动普通 Activity 的场景
DialogActivity Theme.AppCompat.Dialog 模拟启动对话框式 Activity 的场景

2. Activity 生命周期概览

Android 官方将 Activity 的生命周期划分为以下 7 个核心回调

复制代码
        Activity 启动
              │
              ▼
         ┌──────────┐
         │ onCreate │  ← 首次创建,只调用一次
         └────┬─────┘
              ▼
         ┌──────────┐
         │ onStart  │  ← Activity 即将可见
         └────┬─────┘
              ▼
  ┌──────────────┐     ┌───────────────┐
  │  onResume    │◄────│  onRestart    │
  │  (前台可交互) │     │  (重新启动后)  │
  └──────┬───────┘     └───────▲───────┘
         │                     │
         ▼                     │
    ┌──────────┐               │
    │ onPause  │ ── 再次可见 ──►│
    └────┬─────┘
         ▼
    ┌──────────┐
    │ onStop   │  ← Activity 完全不可见
    └────┬─────┘
         ▼
    ┌───────────┐
    │ onDestroy │  ← Activity 被销毁
    └───────────┘

生命周期方法速查表

方法 调用时机 调性 是否可被杀
onCreate() Activity 首次创建 整个生命周期只调一次
onStart() Activity 即将可见(仍在后台) 可调多次
onResume() Activity 获得焦点,可交互 可调多次
onPause() 失去焦点,部分可见(如被对话框遮挡) 可调多次 ✅(Android 7.0+ 不再)
onStop() 完全不可见 可调多次
onDestroy() Activity 被销毁前 只调一次
onRestart() onStop 回到 onStart 可调多次

3. 源码逐行解读

3.1 MainActivity(核心)

java 复制代码
public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");  //  日志打点
        setContentView(R.layout.activity_main);

        // 如果 Activity 是被系统销毁后重建的,恢复保存的临时数据
        if (savedInstanceState != null) {
            String tempData = savedInstanceState.getString("data_key");
            Log.d(TAG, tempData);  // 会打印 "Something you just typed"
        }

        // 按钮1:启动 NormalActivity
        Button startNormalActivity = findViewById(R.id.start_normal_activity);
        startNormalActivity.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, NormalActivity.class);
            startActivity(intent);
        });

        // 按钮2:启动 DialogActivity
        Button startDialogActivity = findViewById(R.id.start_dialog_activity);
        startDialogActivity.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, DialogActivity.class);
            startActivity(intent);
        });
    }

    // 当 Activity 被系统意外销毁时,保存临时数据
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something you just typed";
        outState.putString("data_key", tempData);
    }

    // ========== 以下六个方法全部只打 Log ==========
    @Override protected void onStart()    { super.onStart();    Log.d(TAG, "onStart");    }
    @Override protected void onResume()   { super.onResume();   Log.d(TAG, "onResume");   }
    @Override protected void onPause()    { super.onPause();    Log.d(TAG, "onPause");    }
    @Override protected void onStop()     { super.onStop();     Log.d(TAG, "onStop");     }
    @Override protected void onDestroy()  { super.onDestroy();  Log.d(TAG, "onDestroy");  }
    @Override protected void onRestart()  { super.onRestart();  Log.d(TAG, "onRestart");  }
}
代码要点解析
  • TAG 常量 :定义 "MainActivity" 为日志标签,可通过 adb logcat -s MainActivity 过滤只看该 Activity 的日志。
  • onSaveInstanceState :这是非生命周期方法,用于系统销毁 Activity 前 保存临时状态(如用户输入)。当 Activity 被重建时,数据通过 onCreate(Bundle) 中的 savedInstanceState 恢复。
  • 两个按钮 :分别以普通 Intent 方式启动 NormalActivityDialogActivity,用来观察不同目标 Activity 对 MainActivity 生命周期的影响。

3.2 NormalActivity

java 复制代码
public class NormalActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.normal_layout);
    }
}

这是最简单的 Activity 实现,仅覆写 onCreate 并加载布局。

注意 :它没有覆写 onPauseonStop 等生命周期方法,也没有打日志 ------ 但我们关注的是它对 MainActivity 生命周期的影响


3.3 DialogActivity(对话框主题)

java 复制代码
public class DialogActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dialog_layout);
    }
}

代码与 NormalActivity 几乎一样,关键在于 AndroidManifest 中的主题声明

xml 复制代码
<activity
    android:name=".DialogActivity"
    android:theme="@style/Theme.AppCompat.Dialog" />

Theme.AppCompat.Dialog 使 DialogActivity 以对话框样式显示,这意味着:

  • MainActivity 在后台仍然部分可见
  • MainActivity 只会走到 onPause,不会走到 onStop

对话框式 Activity 并不会让前一个 Activity 完全不可见。


3.4 布局文件

activity_main.xml:

xml 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/start_normal_activity"
        android:layout_width="277dp"
        android:layout_height="141dp"
        android:text="Start NormalActivity" />

    <Button
        android:id="@+id/start_dialog_activity"
        android:layout_width="281dp"
        android:layout_height="191dp"
        android:text="Start DialogActivity" />
</LinearLayout>

两个大按钮,垂直排列,各自负责启动一个子 Activity。

normal_layout.xml / dialog_layout.xml:

xml 复制代码
<LinearLayout ...>
    <TextView
        android:text="This is a normal activity" />
</LinearLayout>

简洁的占位提示文本,仅用于区分当前所处页面。


3.5 AndroidManifest.xml

xml 复制代码
<activity
    android:name=".DialogActivity"
    android:theme="@style/Theme.AppCompat.Dialog"
    android:exported="true" />

<activity
    android:name=".NormalActivity"
    android:exported="false" />

<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
配置项 说明
MainActivityLAUNCHER 应用启动入口
DialogActivity.theme="Theme.AppCompat.Dialog" 对话框主题,关键差异
NormalActivity.exported="false" 不允许外部应用启动

4. 五种场景下的生命周期调用顺序

以下是基于本 Demo 项目,通过 Logcat 实际验证 的调用顺序。

场景一:应用正常启动

复制代码
MainActivity: onCreate
MainActivity: onStart
MainActivity: onResume

结论onCreateonStartonResume,这是每个 Activity 的"标准启动三部曲"。


场景二:点击 "Start NormalActivity"

复制代码
MainActivity: onPause
NormalActivity: onCreate
NormalActivity: onStart
NormalActivity: onResume
MainActivity: onStop        ← MainActivity 完全不可见

结论

  • 新 Activity 的 onResume 在旧 Activity 的 onStop 之前完成,保证新界面先出现,用户体验流畅。
  • 旧 Activity 进入 onPauseonStop ,但没有被销毁

场景三:从 NormalActivity 按返回键

复制代码
NormalActivity: onPause
MainActivity: onRestart    ← 注意!回到 MainActivity 调用的是 onRestart
MainActivity: onStart
MainActivity: onResume
NormalActivity: onStop
NormalActivity: onDestroy

结论

  • MainActivity 不是从 onCreate 重新创建,而是从 onRestartonStartonResume 恢复。
  • NormalActivity 被销毁:onPauseonStoponDestroy

场景四:点击 "Start DialogActivity"

复制代码
MainActivity: onPause      ← 注意!只到 onPause
DialogActivity: onCreate
DialogActivity: onStart
DialogActivity: onResume

结论

  • MainActivity 仅走到 onPause,没有走到 onStop
  • 原因:DialogActivity 是对话框主题,MainActivity 仍然部分可见,所以不需要 onStop

🔑 核心区分onPause = 失去焦点但可能部分可见;onStop = 完全不可见。


场景五:从 DialogActivity 按返回键

复制代码
DialogActivity: onPause
MainActivity: onResume     ← 直接从 onPause 回到 onResume!
DialogActivity: onStop
DialogActivity: onDestroy

结论

  • MainActivity onPause 直接回到 onResume不会调用 onRestartonStart
  • 因为 MainActivity 从未进入 onStop 状态,所以恢复时走的是 onPause → onResume 的"快速恢复"路径。

关键区别onStop → onRestart → onStart(完全可见恢复) vs onPause → onResume(部分可见恢复)。


5. 关键知识点深度剖析

5.1 onPause vs onStop 的区别

对比维度 onPause onStop
Activity 是否可见 部分/完全可见 完全不可见
触发场景 弹窗覆盖、新 Activity 半透明、分屏 新 Activity 全屏覆盖、按 Home 键
恢复路径 onResume() onRestart()onStart()onResume()
适合做的事情 暂停动画、停止摄像头预览 保存持久数据、释放重量级资源

5.2 onSaveInstanceState 的作用

java 复制代码
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("data_key", "Something you just typed");
}
  • 调用时机:Activity 即将被系统销毁但可能重建 时(如旋转屏幕、内存不足),onStop 之前调用
  • 不调用时机:用户主动按返回键关闭 Activity 时不会调用
  • 恢复方式:在 onCreate(Bundle savedInstanceState)onRestoreInstanceState(Bundle) 中取出。

5.3 为什么在 onCreate 中恢复数据?

java 复制代码
if (savedInstanceState != null) {
    String tempData = savedInstanceState.getString("data_key");
    Log.d(TAG, tempData);
}

Demo 中在 onCreatesetContentView 之前判断并恢复 ------ 这样就可以在 UI 初始化之前准备好数据(比如填充 EditText 的内容)。

5.4 完整生命周期状态图

复制代码
                   ┌──────────────┐
        首次启动   │   Activity   │
    ─────────────► │   launched   │
                   └──────┬───────┘
                          │ onCreate()
                          ▼
                   ┌──────────────┐
                   │              │
                   │   Created    │◄──────────────────────────┐
                   │              │                           │
                   └──────┬───────┘                           │
                          │ onStart()                         │
                          ▼                                   │
                   ┌──────────────┐                           │
                   │   Started    │──── onRestart() ──────────┤
                   │              │                           │
                   └──────┬───────┘                           │
                          │ onResume()                        │
                          ▼                                   │
┌──────────────────────────────────────────────┐              │
│                                              │              │
│  ┌──────────────┐                            │              │
│  │   Resumed    │◄──────── onResume() ───────┤              │
│  │ (可交互前台)  │──────── onPause() ────────►│              │
│  └──────────────┘                    ┌───────┴───────┐      │
│                                      │    Paused     │      │
│                                      │ (部分可见)     │      │
└──────────────────────────────────────┴───────┬───────┘      │
                                               │ onStop()     │
                                               ▼              │
                                        ┌──────────────┐      │
                                        │   Stopped    │──────┘
                                        │  (不可见)     │
                                        └──────┬───────┘
                                               │ onDestroy()
                                               ▼
                                        ┌──────────────┐
                                        │  Destroyed   │
                                        │  (已销毁)     │
                                        └──────────────┘

6. 总结

我们从 理论 → 代码 → 日志验证 → 场景模拟 四个维度完整覆盖了 Android Activity 的生命周期:

  1. 7 个生命周期方法 的调用时机和顺序
  2. onPause 和 onStop 的本质区别(部分可见 vs 完全不可见)
  3. onSaveInstanceState 的数据保存与恢复机制
  4. 对话框式 Activity 对父 Activity 生命周期的特殊影响

掌握 Activity 生命周期,是写出稳定、流畅 Android 应用的第一步,也是迈向高级开发的必经之路。


相关推荐
猪脚饭还是好吃的2 小时前
【分享】VideoGuru视频编辑 裁剪拼接,合并调速 解锁会员
android
三少爷的鞋2 小时前
避免 Flow + combine 的首值陷阱:用 StateFlow 保证 UI 始终有状态
android
YIN_尹2 小时前
【Linux系统编程】基础IO第一讲——系统文件IO
android·java·linux·c++
艾iYYY12 小时前
string 类的模拟实现
android·服务器·c语言·c++·算法
xyzzklk13 小时前
解决Salesforce无法向外发送邮件
android·java·开发语言·网络·crm·salesforce·客户关系管理
修炼者14 小时前
Gradle三阶段
android
morchalen15 小时前
安卓framework学习6:Contacts 联系人 APP 日志
android
KANGBboy15 小时前
java知识四(面向对象编程)
android·java·开发语言
AD钙奶-lalala19 小时前
Android Studio新建项目默认不使用Compose模版
android·ide·android studio