lifecycleScope — 是什么、与Lifecycle的绑定以及在Android中的使用

作者: IT Sectr 发布日期: 2026-06-23 阅读时间: 9 分钟

lifecycleScope — 是来自androidx.lifecycle库的内置CoroutineScope,它绑定到Activity、Fragment或任何LifecycleOwner的生命周期,并在组件销毁时自动取消协程。根据Google Android Developers, 2025,lifecycleScope允许安全地启动与UI层相关的协程,而无需担心在Activity或Fragment销毁后执行代码的风险。当LifecycleOwner进入DESTROYED状态时,作用域会自动取消。

要点

  • lifecycleScope — 来自lifecycle-runtime-ktx的CoroutineScope,在Lifecycle的DESTROYED状态下取消
  • lifecycleScope.launch — 启动一个协程,该协程在LifecycleOwner销毁时自动取消
  • launchWhenStarted / launchWhenResumed — 已弃用的方法,被repeatOnLifecycle取代
  • repeatOnLifecycle — 用于启动跟随特定Lifecycle状态的协程的现代API
  • Dispatchers.Main.immediate — lifecycleScope的默认调度器

Android中的lifecycleScope是什么?

lifecycleScope — 是LifecycleOwner(Activity、Fragment、Service)接口上的一个扩展属性,提供了一个绑定到组件完整生命周期的现成CoroutineScope。当LifecycleOwner达到DESTROYED状态时,lifecycleScope会自动取消所有活动的协程。

kotlin
// 在Fragment或Activity中
lifecycleScope.launch {
    delay(1000)
    showSnackbar("你好!")
}

与viewModelScope不同,lifecycleScope在每次LifecycleOwner销毁时都会取消——包括屏幕旋转。这使其非常适合仅在特定屏幕可见时才需要存在的操作。

lifecycleScope在哪些地方可用

lifecycleScope在任何有LifecycleOwner的地方都可用:

  • Activity — AppCompatActivity继承LifecycleOwner
  • Fragment — Fragment继承LifecycleOwner
  • LifecycleService — 具有生命周期的服务
  • ProcessLifecycleOwner — 整个应用程序的生命周期
  • 自定义LifecycleOwner — 任何实现LifecycleOwner的对象

lifecycleScope如何工作:Lifecycle和自动取消

lifecycleScope的自动取消机制基于对Lifecycle事件的订阅。当Lifecycle从CREATED下降到DESTROYED时,作用域被取消。

Lifecycle状态

状态描述作用域活动
CREATEDLifecycleOwner已创建,onCreate已执行
STARTEDLifecycleOwner可见(onStart)
RESUMEDLifecycleOwner在前台(onResume)
DESTROYEDLifecycleOwner已销毁(onDestroy)否(作用域已取消)

lifecycleScope的内部结构

lifecycleScope被创建为CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)并存储在Lifecycle内部。当Lifecycle进入DESTROYED状态时,会调用scope.cancel()。该机制通过LifecycleEventObserver实现,该观察者在首次访问作用域时订阅生命周期事件。

旋转时的行为

当屏幕旋转时,Activity被销毁(onDestroy)并重新创建。lifecycleScope与旧Activity一起被取消,并为新Activity创建新的作用域实例。这是与viewModelScope的根本区别,后者在旋转时得以保留。

lifecycleScope API:launch、launchWhen和repeatOnLifecycle

Lifecycle库提供了几种通过lifecycleScope启动协程的方式。让我们看看API从弃用方法到现代方法的演变。

lifecycleScope.launch — 基本启动

最简单的方式——lifecycleScope.launch { ... }。协程立即启动并在DESTROYED时取消。但是,它可能在UI不可见时执行代码(例如,在onStop之后的后台)。这并不总是可取的。

已弃用:launchWhenCreated / launchWhenStarted / launchWhenResumed

这些方法在Lifecycle低于指定状态时暂停协程执行,并在返回时恢复。但它们在lifecycle-runtime-ktx 2.6.0中被标记为@Deprecated,因为:

  • 它们不会取消协程——只是暂停
  • 它们导致挂起协程的积累,消耗内存
  • 它们在快速状态切换时造成竞态条件

现代API:repeatOnLifecycle

repeatOnLifecycle — Google推荐的启动与生命周期同步的协程的方式。每当Lifecycle达到指定状态时,它都会取消并重新启动协程。

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.uiState.collect { state ->
            updateUI(state)
        }
    }
}

传递给repeatOnLifecycle的协程在Lifecycle达到STARTED时启动,并在低于STARTED时取消。当返回到STARTED时,协程从头重新启动。这是安全且高效的——没有协程处于暂停挂起状态。

flowWithLifecycle — 用于Flow

为了在考虑生命周期的情况下从Flow收集数据,有flowWithLifecycle操作符。它会在Lifecycle状态变化时自动停止和恢复收集:

kotlin
viewModel.uiState
    .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
    .onEach { state -> updateUI(state) }
    .launchIn(lifecycleScope)

flowWithLifecycle操作符——在UI层安全订阅Flow的最简洁方式。

lifecycleScope使用示例

让我们看看在Kotlin的Android应用中使用lifecycleScope的三个真实场景。

示例1:仅在屏幕可见时订阅位置更新

kotlin
class MapFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                locationProvider.observeLocation().collect { loc ->
                    updateMapMarker(loc)
                }
            }
        }
    }
}

协程在Fragment变为可见时启动(STARTED),并在离开屏幕时取消(STOPPED)。如果用户切换到其他应用,位置更新不会消耗电池。

示例2:在Fragment启动时运行动画

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.RESUMED) {
        animateFadeIn(titleView)
        delay(200)
        animateSlideUp(contentView)
    }
}

动画仅在Fragment在前台时启动(RESUMED)。如果用户在动画期间最小化应用,协程被取消,返回时动画重新启动。

示例3:在可见屏幕上定期同步数据

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        while (isActive) {
            syncData()
            delay(30_000L)
        }
    }
}

数据每30秒同步一次,但仅在屏幕可见时。isActive检查协程是否未被取消,确保在离开屏幕时安全退出循环。

lifecycleScope与viewModelScope:应用场景

两个作用域都绑定到生命周期,但绑定到不同的方面。理解区别对于正确的Android应用程序架构至关重要。

关键区别

viewModelScope绑定到ViewModel,后者能经受屏幕旋转。lifecycleScope绑定到LifecycleOwner(Activity/Fragment),后者在旋转时被销毁并重新创建。这决定了它们的应用场景。

何时使用lifecycleScope

  • 订阅系统事件(位置、传感器、相机)
  • 绑定到特定屏幕的动画和UI效果
  • 考虑屏幕可见性的分块数据加载
  • 离开屏幕时应停止的操作

何时使用viewModelScope

  • 从Repository加载数据
  • 需要经受旋转的业务逻辑
  • 数据缓存和处理
  • 任何结果在旋转后需要的操作

组合使用

在实践中,两种作用域的组合很常见:viewModelScope加载数据并管理状态,lifecycleScope从ViewModel订阅Flow,同时考虑屏幕的生命周期。这种职责分离被认为是现代Android开发中的最佳实践

使用lifecycleScope时的常见错误

让我们看看开发人员在使用lifecycleScope时最常见的四个错误。

错误1:使用lifecycleScope代替viewModelScope加载数据

如果在lifecycleScope.launch中启动数据加载,屏幕旋转时协程将被取消,数据必须重新加载。对于长时间运行的操作,请使用viewModelScope。lifecycleScope——仅用于与UI相关的任务。

错误2:在没有repeatOnLifecycle的情况下收集Flow

在lifecycleScope.launch内部直接调用viewModel.someFlow.collect { ... }即使在屏幕不可见时也会继续收集数据。这可能导致后台UI更新和不必要的开销。始终使用repeatOnLifecycleflowWithLifecycle

错误3:离开屏幕时忘记取消

虽然lifecycleScope在DESTROYED时被取消,但挂起点(suspend)之后的代码可能在突然取消时不会执行。除非使用NonCancellable,否则不要依赖挂起调用之后代码的执行。

错误4:使用已弃用的launchWhenStarted而不是repeatOnLifecycle

launchWhenStarted及其类似物不会取消协程,只会暂停它。如果屏幕在前台和后台之间多次切换,协程会累积延迟调用。请迁移到repeatOnLifecycle——这是与Lifecycle同步的唯一正确方式。

常见问题

lifecycleScope和GlobalScope有什么区别?

lifecycleScope在LifecycleOwner销毁时自动取消。GlobalScope在整个应用程序运行期间都存在。lifecycleScope中的协程不能在组件销毁后更新UI,而GlobalScope可以,这会导致崩溃。始终在UI层使用lifecycleScope。

可以在ViewModel中使用lifecycleScope吗?

不,ViewModel不是LifecycleOwner,因此lifecycleScope在其中不可用。ViewModel使用viewModelScope。如果代码需要在两个上下文中执行——将逻辑提取到带有挂起函数的use case或repository中。

重复调用repeatOnLifecycle时会发生什么?

每次repeatOnLifecycle调用都会创建一个新的协程,该协程在达到指定的Lifecycle状态时启动代码块。如果为同一状态调用两次repeatOnLifecycle,两个块将独立运行。通常,在onViewCreated中调用一次就足够了。

可以为lifecycleScope设置自定义Dispatcher吗?

不能直接更改lifecycleScope的调度器——它使用Dispatchers.Main.immediate。在协程块内部,可以通过withContext切换到其他调度器。对于测试,请使用带有LifecycleOwner的TestDispatcher。

lifecycleScope是在onPause还是onDestroy中取消?

lifecycleScope在LifecycleOwner进入DESTROYED状态时取消(在onDestroy之后)。简单的lifecycleScope.launch调用不会在onPause或onStop中取消。要在进入后台时暂停,请使用repeatOnLifecycle(STARTED)或repeatOnLifecycle(RESUMED)。

总结

  • lifecycleScope — 绑定到LifecycleOwner的CoroutineScope,通过LifecycleEventObserver在DESTROYED时自动取消
  • Dispatchers.Main.immediate — 默认调度器,确保无需不必要的切换即可安全更新UI
  • repeatOnLifecycle — 现代API,用于在指定的Lifecycle状态下启动协程,并具有自动取消和重启功能
  • flowWithLifecycle — 在考虑生命周期的情况下从UI安全收集Flow的操作符
  • launchWhenStarted已弃用 — 使用repeatOnLifecycle代替暂停,它会取消协程而不是暂停
  • lifecycleScope与viewModelScope — lifecycleScope用于UI操作(动画、位置),viewModelScope用于数据和业务逻辑
  • 屏幕旋转 — lifecycleScope在旋转时取消,viewModelScope保留;根据任务选择作用域

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

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

讨论项目

另请阅读