3. Activity生命周期与启动模式

说实话,Activity是Android里最基础也最核心的概念。你写的每个界面,背后都是一个Activity在撑着。我记得刚入行那会儿,面试官最爱问的就是「说说Activity的生命周期」。当时觉得背下来就行,后来真做项目才发现——光背没用,得理解它为什么这么设计。

今天咱们就把这块彻底讲透。包括四种状态、七个回调方法、四种启动模式,还有Intent怎么跳转。嗯,内容不少,但都是干货。

3.1 Activity的四种状态

Activity在运行过程中,会在四种状态之间切换。说白了,就是系统根据你的操作和资源情况,给Activity安排不同的「活法」。

状态 说明 典型场景
运行状态 Activity位于前台,用户可交互 你正在刷朋友圈
暂停状态 Activity被部分遮挡,但仍可见 弹出一个对话框
停止状态 Activity完全不可见 按Home键回到桌面
销毁状态 Activity被系统回收或主动finish 按返回键退出

你想想看,系统为什么要搞这四种状态?其实就是为了合理分配内存和CPU。运行状态的Activity优先级最高,系统轻易不会杀它。停止状态的Activity呢?如果内存不够,系统第一个拿它开刀。

注意: 我曾经在项目里遇到过一个问题——用户按Home键后,再回来发现应用重启了。后来排查发现,是因为我在停止状态下没有保存关键数据,Activity被系统回收了。所以,停止状态下的数据保存一定要做

3.2 七个回调方法详解

Activity的生命周期回调,说白了就是系统给你发的「通知」。每个通知告诉你:你的Activity现在处于什么阶段,你可以趁机做点啥。

我个人习惯把七个回调分成三组来记:

3.2.1 创建与销毁组

  • onCreate():Activity第一次创建时调用。做初始化工作——加载布局、绑定控件、初始化数据。只调用一次。
  • onDestroy():Activity被销毁前调用。释放资源、取消注册、停止线程。也是只调用一次。

这里有个坑:onCreate里不要做耗时操作。我见过有人直接在onCreate里请求网络,结果界面卡了好几秒才出来。用户体验极差。

3.2.2 可见与不可见组

  • onStart():Activity变得可见,但还不能交互。可以在这里做一些准备动画或数据预加载。
  • onStop():Activity完全不可见。可以在这里停止动画、释放大对象。

为什么会这样?因为从onStart到onStop之间,用户可能只是短暂离开。比如接了个电话,这时候你不需要重新创建Activity,只需要恢复界面状态就行。

3.2.3 前台与后台组

  • onResume():Activity进入前台,可以跟用户交互了。通常在这里开启摄像头、传感器等。
  • onPause():Activity失去焦点,但部分可见。保存用户输入的数据、暂停动画。

嗯,这里要注意:onPause里不能做耗时操作,因为它执行完下一个Activity才能显示。我曾经在onPause里写了个数据库写入操作,结果界面切换卡了半秒,被产品经理追着改。

完整生命周期路径:
onCreate → onStart → onResume → (运行中) → onPause → onStop → onDestroy

常见分支路径:
按Home键:onPause → onStop
按返回键:onPause → onStop → onDestroy
从后台恢复:onRestart → onStart → onResume

3.3 四种启动模式

启动模式解决的是「Activity怎么入栈」的问题。Android用任务栈来管理Activity,默认是后进先出。但实际开发中,我们经常需要改变这个规则。

我画了一张图,帮你理解四种启动模式的区别:

Activity四种启动模式对比 Standard 每次启动都创建新实例 Activity A Activity A Activity A 栈顶重复创建 SingleTop 栈顶复用,否则新建 Activity B Activity A B在栈顶,再次启动B 复用B,不走onCreate SingleTask 栈内唯一,清除上方 Activity C Activity B Activity A 启动A,清除B和C A回到栈顶 SingleInstance 独立任务栈 Activity D D独占一个栈 其他Activity在 另一个栈中 再次启动D 直接复用

3.2.1 Standard(标准模式)

默认模式。每次启动都创建新实例,不管栈里有没有。我刚开始写Android时,用Standard模式启动了一个页面,用户点了五次按钮,按返回键就要按五次才能退出。这就是典型的「栈堆积」问题。

3.2.2 SingleTop(栈顶复用模式)

如果要启动的Activity已经在栈顶,直接复用,不走onCreate,而是走onNewIntent。适合通知栏点击跳转的场景——用户点一次通知进页面,再点一次不应该创建新页面。

3.2.3 SingleTask(栈内复用模式)

栈内只允许有一个实例。如果已经存在,会把它上面的Activity全部出栈,然后调用onNewIntent。我一般在主页面用这个模式,防止用户从其他页面跳回主页时产生多个主页实例。

3.2.4 SingleInstance(单实例模式)

这个最特殊。它单独占一个任务栈,整个系统里只有一个实例。适合那种「全局唯一」的页面,比如来电界面、闹钟响铃界面。嗯,这个模式用得少,但用对了很管用。

我的建议: 启动模式在AndroidManifest.xml里配置,也可以在Intent里通过flag临时指定。我个人习惯在Manifest里配好默认行为,特殊场景再用flag覆盖。这样代码更清晰。

3.4 Intent与Activity跳转

Intent是Android里连接组件的「信使」。说白了,你想启动一个Activity,就得通过Intent告诉系统:你要去哪,带什么东西。

3.4.1 显式Intent

直接指定目标Activity的类名。最常见的方式:

// 从当前Activity跳转到SecondActivity
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);

3.4.2 隐式Intent

不指定具体类名,而是通过action、category等条件让系统帮你匹配。适合跨应用跳转:

// 打开浏览器
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.example.com"));
startActivity(intent);

3.4.3 携带数据跳转

用putExtra传数据,用getXXXExtra接收:

// 发送方
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("user_id", 1001);
intent.putExtra("user_name", "张三");
startActivity(intent);

// 接收方(在DetailActivity的onCreate中)
int userId = getIntent().getIntExtra("user_id", 0);
String userName = getIntent().getStringExtra("user_name");
避坑指南: 我曾经在Intent里传了一个大Bitmap,结果导致TransactionTooLargeException。Intent传数据有大小限制,大约1MB。大数据请用文件路径或数据库ID代替。

3.4.4 启动Activity并获取结果

有时候你需要从目标页面带回数据,比如选照片、填表单:

// 启动
Intent intent = new Intent(this, PickActivity.class);
startActivityForResult(intent, REQUEST_CODE_PICK);

// 在目标页面设置结果
Intent resultIntent = new Intent();
resultIntent.putExtra("selected_item", "item_1");
setResult(RESULT_OK, resultIntent);
finish();

// 在当前页面接收结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_PICK && resultCode == RESULT_OK) {
        String item = data.getStringExtra("selected_item");
        // 处理选中的结果
    }
}

嗯,这里要注意:startActivityForResult在Android 11以上已经标记为deprecated,官方推荐用Activity Result API。不过老项目里还是经常见到,你得能看懂。

核心要点回顾:
  • 四种状态:运行、暂停、停止、销毁。系统根据优先级管理Activity
  • 七个回调:onCreate/onDestroy做初始化/释放,onStart/onStop管可见性,onResume/onPause管前台交互
  • 四种启动模式:Standard默认新建,SingleTop栈顶复用,SingleTask栈内唯一,SingleInstance独立栈
  • Intent跳转:显式指定类名,隐式靠条件匹配,putExtra传数据,startActivityForResult拿结果

Activity这块内容,说实话,你写三五个项目之后自然就熟了。但刚开始学的时候,一定要动手写代码验证。我建议你写个Demo,在每个回调里打印日志,然后各种操作(按Home键、旋转屏幕、跳转页面),看看日志输出顺序。这样印象最深。


公众号:蓝海资料掘金营,微信deep3321