3、Activity与生命周期:Activity的创建、启动、销毁,以及onCreate、onStart、onResume、onPause、onStop、onDestroy回调详解。

各位同学,咱们今天来聊聊Android开发里最基础、也最绕不开的一个话题——Activity的生命周期。

说实话,我刚开始学Android那会儿,觉得这玩意儿不就是几个回调方法嘛,背下来就行了。直到后来线上出了个诡异的Bug,用户反馈说“App切到后台再回来,数据丢了”。我排查了半天,最后发现是生命周期没处理好。嗯,从那以后,我再也不敢小看这几个回调了。

你想想看,Activity就像是你App里的一个“页面管理员”。它什么时候出生、什么时候上班、什么时候摸鱼、什么时候下班,都得有一套规矩。这套规矩,就是生命周期。

3.1 Activity是什么?

简单说,Activity就是一个用户界面的容器。它负责展示UI,并处理用户的交互事件。每个Activity对应一个屏幕(或者一个浮层)。

我个人习惯把Activity比作“舞台”。你写的布局文件就是舞台上的布景,而生命周期回调就是舞台监督的指令——开灯、拉幕、演员上场、谢幕、关灯。

核心要点:Activity是Android四大组件之一,是用户与App交互的入口。每个Activity在AndroidManifest.xml中注册后才能使用。

3.2 生命周期回调详解

Android系统为了管理Activity的状态,定义了6个核心回调方法。它们按固定顺序执行,形成一个完整的生命周期。

先看一张流程图,我亲手画的,帮你理清这6个方法的调用顺序和对应状态:

Activity 生命周期流程图 onCreate() onStart() onResume() ← Activity 可见且可交互 onPause() onStop() onDestroy() 用户返回 用户重新打开 注:虚线表示用户操作后重新进入的路径

这张图你看懂了吗?从上到下是Activity从创建到销毁的完整路径。虚线表示用户操作后重新进入的路径。说白了,这就是Activity的一生。

3.3 六个回调方法,逐个击破

3.3.1 onCreate() —— 出生

这是Activity生命周期的起点。系统创建Activity时调用,且只调用一次。

在这里,你应该做这些事:

  • 调用 setContentView() 加载布局
  • 初始化 View 和成员变量
  • 绑定 Adapter、设置监听器
  • 恢复之前保存的状态(从 Bundle 中读取)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 恢复之前保存的状态
    if (savedInstanceState != null) {
        String userName = savedInstanceState.getString("user_name");
        // 恢复数据...
    }

    // 初始化控件
    mTextView = findViewById(R.id.tv_hello);
    mButton = findViewById(R.id.btn_click);
    mButton.setOnClickListener(v -> {
        // 处理点击事件
    });
}

我的经验:onCreate里不要做耗时操作。我曾经在一个项目里直接在onCreate里加载网络数据,结果导致启动白屏好几秒。后来把网络请求挪到了onStart里,配合Loading动画,体验好多了。

3.3.2 onStart() —— 准备上台

Activity即将变得可见,但还不能与用户交互。说白了,就是“幕布刚拉开,演员还没就位”。

适合在这里做的事:

  • 注册广播接收器
  • 绑定Service
  • 开始一些轻量级的动画

3.3.3 onResume() —— 正式演出

Activity变得可见且可交互。用户终于可以点按钮、滑动列表了。

注意:onResume是生命周期里最“活跃”的状态。用户每次回到这个Activity,都会走onResume。

@Override
protected void onResume() {
    super.onResume();
    // 开始轮询、开启传感器监听等
    startLocationUpdates();
}

避坑指南:我曾经在onResume里忘记调用super.onResume(),结果导致Fragment的动画全部失效。找了半天才发现是这个问题。记住:super方法一定要调,而且要在你写逻辑之前调。

3.3.4 onPause() —— 暂停

Activity即将失去焦点,但依然可见。比如弹出了一个Dialog,或者用户按了Home键。

这里适合做:

  • 保存未持久化的数据(比如草稿)
  • 停止动画
  • 释放一些系统资源

重要:onPause的执行时间非常短(Android 12之前是500ms,之后是100ms)。所以千万别在这里做耗时操作,比如网络请求、数据库写入。

3.3.5 onStop() —— 退到后台

Activity完全不可见了。用户打开了另一个App,或者按了返回键。

适合做的事:

  • 取消网络请求
  • 注销广播接收器
  • 释放大内存对象(比如Bitmap)
@Override
protected void onStop() {
    super.onStop();
    // 取消网络请求
    if (mCall != null && !mCall.isCanceled()) {
        mCall.cancel();
    }
    // 注销广播
    unregisterReceiver(mReceiver);
}

3.3.6 onDestroy() —— 谢幕

Activity被销毁了。可能是用户主动finish(),也可能是系统为了回收内存而杀掉它。

在这里,你需要清理所有资源:

  • 关闭数据库连接
  • 解绑Service
  • 停止后台线程

核心原则:你在onCreate里创建了什么,就在onDestroy里销毁什么。一一对应,不要漏。

3.4 生命周期完整调用顺序

咱们用表格总结一下,不同场景下回调的调用顺序:

场景 调用顺序
首次启动Activity onCreate → onStart → onResume
按Home键回到桌面 onPause → onStop
从桌面回到Activity onRestart → onStart → onResume
按返回键退出 onPause → onStop → onDestroy
屏幕旋转(未配置configChanges) onPause → onStop → onDestroy → onCreate → onStart → onResume
被系统回收后重新创建 onCreate(带savedInstanceState)→ onStart → onResume

你发现没有?屏幕旋转会导致Activity销毁重建。这是Android早期设计的一个“坑”。我个人习惯在AndroidManifest里配置 android:configChanges="orientation|screenSize" 来避免不必要的重建,但前提是你自己能处理好配置变化。

3.5 实战中的避坑指南

讲了这么多理论,咱们来点实际的。我在项目中踩过的坑,分享给你:

  1. 不要在onPause里做耗时操作——系统会等onPause执行完才显示下一个Activity。你拖得越久,用户感觉越卡。
  2. onSaveInstanceState和onRestoreInstanceState——系统回收Activity时,会调用onSaveInstanceState保存数据。你需要在onCreate或onRestoreInstanceState里恢复。记住:这个方法只在Activity被“非正常”销毁时才会调用。用户按返回键正常退出,不会触发。
  3. Handler和内部类导致的内存泄漏——如果你在Activity里创建了Handler,并且发了一个延迟消息,在Activity销毁时消息还没处理,那这个Handler会持有Activity的引用,导致Activity无法被GC回收。解决办法:在onDestroy里移除所有消息和回调。
@Override
protected void onDestroy() {
    super.onDestroy();
    // 移除所有消息和回调,防止内存泄漏
    mHandler.removeCallbacksAndMessages(null);
}

我曾经踩过的坑:有一个版本上线后,用户反馈说“App切到后台再切回来,页面数据全没了”。我查了半天,发现是因为在onStop里清空了列表数据,但没有在onStart里重新加载。后来我改成了:只在onDestroy里清数据,onStop里只暂停刷新,onStart里恢复刷新。问题解决了。

3.6 小结

Activity的生命周期,说白了就是一套“状态机”。系统通过这6个回调,告诉你Activity当前处于什么状态,以及接下来要进入什么状态。

你不需要死记硬背每个回调的调用顺序。你只需要记住一个原则:轻量、对称、及时

  • 轻量:每个回调里不要做耗时操作
  • 对称:onCreate对应onDestroy,onStart对应onStop,onResume对应onPause
  • 及时:该释放的资源及时释放,该保存的数据及时保存

做到这三点,你的Activity就不会出大问题。


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