跳到主要内容

LiveData

问题

LiveData 是什么?它和 Flow 相比有哪些优缺点?

答案

核心概念

LiveData 是一个具有生命周期感知能力的可观察数据容器。它只会在观察者处于活跃状态(STARTEDRESUMED)时发送更新,避免了崩溃和内存泄漏。

class UserViewModel : ViewModel() {
// 对内可变
private val _user = MutableLiveData<User>()
// 对外只读
val user: LiveData<User> = _user

fun loadUser(id: Long) {
viewModelScope.launch {
_user.value = repository.getUser(id) // 主线程赋值
// _user.postValue(user) // 子线程使用 postValue
}
}
}

// Activity 中观察
viewModel.user.observe(this) { user ->
binding.nameText.text = user.name
}

LiveData 操作符

// Transformations.map —— 数据转换
val userName: LiveData<String> = user.map { it.name }

// Transformations.switchMap —— 根据值切换数据源
val userItems: LiveData<List<Item>> = userId.switchMap { id ->
repository.getItemsLiveData(id)
}

// MediatorLiveData —— 合并多个源
val result = MediatorLiveData<String>()
result.addSource(liveData1) { result.value = combine(it, liveData2.value) }
result.addSource(liveData2) { result.value = combine(liveData1.value, it) }

LiveData vs Kotlin Flow

特性LiveDataStateFlow / SharedFlow
生命周期感知✅ 自动需要 repeatOnLifecycle
线程安全postValueemit(协程安全)
操作符有限(map/switchMap)丰富(与 Kotlin 流一致)
粘性事件✅(新观察者收到最后值)StateFlow 有,SharedFlow 可配置
背压处理支持
Java 兼容✅ 好需要额外适配
推荐场景仅在 UI 层使用推荐用 Flow 替代
官方建议

Google 官方推荐在新项目中使用 Kotlin Flow + repeatOnLifecycle 替代 LiveData。LiveData 仅在需要 Java 兼容时使用。


常见面试问题

Q1: LiveData 的粘性事件问题是什么?

答案

新注册的 Observer 会立即收到 LiveData 中最后一次设置的值,这就是"粘性"。对于一次性事件(如 Toast、导航)来说会导致重复消费。

解决方案

  • 使用 SingleLiveEvent(Google 示例,但不推荐)
  • 封装 Event 包装类,标记是否已消费
  • 推荐:改用 SharedFlow(replay = 0)Channel
// Event 包装类
open class Event<out T>(private val content: T) {
private var hasBeenHandled = false
fun getContentIfNotHandled(): T? =
if (hasBeenHandled) null else { hasBeenHandled = true; content }
}

Q2: setValuepostValue 的区别?

答案

  • setValue():必须在主线程调用,同步更新值并立即通知观察者
  • postValue():可在任何线程调用,通过 Handler 将更新 post 到主线程。如果连续调用多次,只有最后一次值生效

Q3: LiveData 是如何感知生命周期的?

答案

LiveData.observe() 内部将 Observer 包装为 LifecycleBoundObserver,它实现了 LifecycleEventObserver

  1. 当 Lifecycle 状态 >= STARTED 时,标记为活跃,分发数据
  2. 当 Lifecycle 状态 < STARTED 时,标记为非活跃,停止分发
  3. 当 Lifecycle 进入 DESTROYED 时,自动移除 Observer

相关链接