onResume — 基础,Android中与用户交互

作者: IT Sectr 发布日期: 2026-03-04 阅读时间: 10 分钟

onResume — 是Android生命周期方法,当Activity或Fragment进入前台并获得输入焦点时被调用。在此状态下,屏幕已准备好与用户交互:所有触摸事件、按键和手势都定向到此组件。onResume是Activity的工作状态,应用程序大部分时间都在此状态中度过。正是在这里打开相机、启动视频播放、开始语音识别并注册需要独占访问的传感器监听器。有关Activity完整生命周期的更多信息,请阅读文章Activity Lifecycle

要点

  • onResume — Activity在前台具有输入焦点; 在onStart之后或从对话框返回时调用
  • 独占资源 — 相机、麦克风、视频捕获在onResume中打开,在onPause中关闭
  • onResume/onPause配对 — 需要完全焦点的资源由此配对管理; 在onResume中注册,在onPause中释放
  • onResume vs onStart — onStart = 可见性,onResume = 交互; 对话框覆盖onResume但不覆盖onStart
  • 时间安排 — onResume必须快速; 长时间操作会延迟界面响应
  • Fragment.onResume — 在Activity.onResume之后调用,当Fragment准备好交互时
  • Jetpack中的onResume — lifecycleScope和LiveData使用onResume自动管理订阅

Android中onResume方法的基础

onResume — 是Activity生命周期的第三个方法,在onStart之后调用,表示屏幕已准备好与用户完全交互. 此时,Activity位于任务栈(back stack)的顶部,系统将所有输入事件定向到它,应用程序可以开始任何需要用户积极参与的操作:视频通话、游戏、录音、在Canvas上绘图。

onResume属于前台生命周期(foreground lifetime)— 即onResume和onPause之间的时间间隔。这是Activity最活跃的工作期,应用程序消耗最大资源:处理器处理触摸、GPU渲染动画、相机和麦克风用于视频捕获。理解这一生命周期级别对于优化能耗至关重要 — 在onResume中打开的资源必须在onPause中立即关闭。

根据Google I/O 2025的数据,Activity在一次会话中处于onResume状态的平均时间为新闻应用2–5分钟,游戏和即时通讯应用15–30分钟。其余时间Activity处于onPause、onStop或onDestroy状态。这意味着优化onResume代码能在性能和电池续航方面带来最大收益。

Activity中的onResume

在Activity中,onResume方法在每次屏幕获得输入焦点时被调用 — 首次启动时、从其他Activity返回时、关闭对话框时、设备解锁时。这是一个热方法,可能在一次会话中被多次调用,其实现应尽可能轻量。

kotlin
class CameraActivity : AppCompatActivity() {
    private var cameraProvider: ProcessCameraProvider? = null
    private var preview: Preview? = null

    override fun onResume() {
        super.onResume()
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            cameraProvider = cameraProviderFuture.get()
            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
            preview = Preview.Builder().build().also {
                it.setSurfaceProvider(binding?.viewFinder?.surfaceProvider)
            }
            try {
                cameraProvider?.unbindAll()
                cameraProvider?.bindToLifecycle(
                    this, cameraSelector, preview
                )
            } catch (e: Exception) {
                Log.e("Camera", "绑定相机失败", e)
            }
        }, ContextCompact.getMainExecutor(this))
    }

    override fun onPause() {
        super.onPause()
        cameraProvider?.unbindAll()
        preview = null
    }
}

CameraX示例展示了onResume/onPause的经典用法:相机是一种独占资源,同一时间只能由一个应用程序使用。通过bindToLifecycle将相机绑定到生命周期会自动在onPause中关闭相机,但显式调用unbindAll可确保立即释放。这在Activity之间切换时尤为重要:相机必须在其他Activity尝试打开之前释放。

Fragment中的onResume

Fragment中的onResume在其包含的Activity收到onResume后被调用. 但由于FragmentManager和ViewPager的特性,Fragment的onResume调用时刻可能相对于Activity延迟。例如,在offscreenPageLimit = 1的ViewPager中,Fragment只有在成为当前页面时才收到onResume,而不是在Activity启动时。

kotlin
class VideoPlayerFragment : Fragment() {
    private var exoPlayer: ExoPlayer? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        exoPlayer = ExoPlayer.Builder(requireContext()).build()
        binding?.playerView?.player = exoPlayer
    }

    override fun onResume() {
        super.onResume()
        exoPlayer?.play()
        if (userVisibleHint) {
            startBiometricAuth()
        }
    }

    override fun onPause() {
        exoPlayer?.pause()
        stopBiometricAuth()
        super.onPause()
    }
}

检查Fragment.onResume中的userVisibleHint对于ViewPager是必要的:Fragment可能收到onResume但被相邻页面隐藏(例如,在动画过渡期间)。在这种情况下,在onResume中启动视频或生物识别而不检查可见性将导致意外行为。从Fragment 1.5.0开始,建议使用FragmentTransaction.setMaxLifecycle()精确控制ViewPager2中片段的生命周期。

onResume vs onStart: 何时使用哪个

开发人员经常混淆onStart和onResume,将代码放在错误的方法中。主要规则:onStart — 用于在可见性下工作的资源; onResume — 用于需要输入焦点的资源. 让我们看看具体场景和方法的选择。

操作方法理由
订阅地理位置onStart / onStopGPS在部分可见性下可以工作
打开相机onResume / onPause相机 — 独占资源
BroadcastReceiveronStart / onStop系统事件不需要焦点
视频播放onResume / onPause视频必须对用户可见
蓝牙扫描onStart / onStop扫描可以在后台继续
录音机(MediaRecorder)onResume / onPause录音需要活跃的UI
传感器监听器onResume / onPause用于游戏和手势的传感器
数据更新onStart出现时需要新鲜数据

实用规则:如果操作应在对话框出现时中断 — 使用onResume/onPause。如果操作可以在屏幕部分覆盖时继续 — 使用onStart/onStop。例如,视频播放器应在打开对话框时暂停视频(onPause),而地理位置可以继续更新(保持在onStart)。

独占资源管理

独占资源是设备组件,在特定时刻只能由一个应用程序使用. 相机、麦克风、视频输出(MediaProjection)、读取模式下的NFC适配器、配件模式下的USB设备 — 所有这些资源必须在onResume中打开并在onPause中释放。

使用MediaRecorder

MediaRecorder用于录制音频和视频. 请求权限和准备MediaRecorder在onCreate中完成,开始录制在onResume中。如果用户切换到其他应用程序,onPause暂停录制,onResume恢复录制。这是录音机和视频录制应用程序的标准行为。

kotlin
private var mediaRecorder: MediaRecorder? = null
private var isRecording = false

override fun onResume() {
    super.onResume()
    if (isRecording) {
        mediaRecorder?.resume()
    }
}

override fun onPause() {
    if (isRecording) {
        mediaRecorder?.pause()
    }
    super.onPause()
}

BiometricPrompt和onResume

生物识别认证(BiometricPrompt)只应在Activity处于onResume状态时调用. 如果在onCreate或onStart中调用,生物识别对话框可能在Activity完成初始化之前出现,导致结果处理不正确。在onResume中调用确保生物识别窗口在正确的上下文中显示。

模式和推荐

让我们看看onResume工作的三种经过验证的模式,这些模式应用于商业项目:重置不活动计时器、更新可见数据以及与Jetpack Navigation集成。

重置不活动计时器

在具有机密数据的应用程序中(银行、医疗卡)onResume用于重置自动退出计时器. 如果用户积极与应用程序交互,onResume在每次屏幕切换时被调用,计时器重置。如果用户最小化应用程序,onPause停止计时器,返回时onResume要么重置它,要么要求重新认证。

返回时更新数据

应在每次返回屏幕时显示最新数据的列表在onResume中更新. 例如,如果用户在另一个Activity中创建了新记录并返回,onResume从本地数据库或ViewModel缓存重新加载列表。这确保了数据的一致性,无需手动调用notifyDataSetChanged。

kotlin
override fun onResume() {
    super.onResume()
    // ActivityResultLauncher返回了结果 — 更新列表
    viewModel.refreshList()
    // 重置不活动计时器
    inactivityTimer.reset()
}

Jetpack Navigation和onResume

在Jetpack Navigation中,片段的onResume在通过返回导航每次回到它时被调用. 此属性用于重置UI状态:隐藏键盘、清除搜索字段、更新工具栏标题。OnBackPressedCallback与onResume结合提供对导航的完全控制,无需重复代码。

常见问题

用简单的话说,onResume和onStart之间的区别是什么?

onStart — 屏幕可见。onResume — 屏幕活跃并准备好交互. 想象一下:你看电视(onStart),但把遥控器拿在手里(onResume)。电视总是可见的,但交互只有用遥控器才开始。如果有人用窗帘遮住电视 — 屏幕不再可见(onStop)。如果遥控器被拿走 — 交互停止(onPause),但电视仍然可见。

onResume多长时间被调用一次?

onResume每次Activity获得输入焦点时被调用. 最少次数 — 一次(启动时)。最大次数取决于使用场景:屏幕之间切换、打开对话框、快速锁定和解锁设备 — 每个这样的场景在返回屏幕时都会调用onResume。

为什么onResume是打开相机的最佳位置?

相机 — 独占资源,同一时间只对一个应用程序可用. 如果在onCreate或onStart中打开相机,即使您的应用程序不活跃,它也会被锁定,其他应用程序无法使用。onResume确保相机仅在Activity在前台时打开,而onPause立即关闭它。这是Android开发的标准,在CameraX和Camera2 API文档中有明确规定。

onResume可能在onStart之后不被调用吗?

是的,如果Activity在出现后立即被另一个Activity覆盖,onResume可能不会发生. 例如,Activity A在onCreate或onStart方法中启动Activity B。在这种情况下,A收到onStart → onPause → onStop,跳过onResume。系统不调用onResume,因为Activity A从未获得输入焦点。

在onResume中不应该做什么?

在onResume中不能执行长时间同步操作:从网络加载大量数据、复杂的SQL查询、图像处理。onResume方法在UI线程中运行,任何超过100–200毫秒的阻塞都会导致界面响应延迟。所有繁重操作都应该是异步的 — 通过协程、RxJava或WorkManager。也不建议在onResume中无检查地调用finish() — 这可能导致无限重建循环。

总结

  • onResume — 带输入焦点的前台状态; Activity准备好与用户交互
  • 独占资源 — 相机、麦克风、视频捕获在onResume中打开,在onPause中关闭
  • onResume vs onStart — onStart用于可见资源,onResume用于活动资源; 对话框中断onResume但不中断onStart
  • 速度 — onResume必须轻量; 所有繁重操作异步
  • Fragment.onResume — 取决于ViewPager中的可见性; 检查userVisibleHint或使用setMaxLifecycle
  • 典型任务 — 重置计时器、返回时更新数据、管理BiometricPrompt
  • onResume/onPause配对 — 具有独占访问权限的资源仅由此配对管理

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读