3、LiveData基础:LiveData的创建与观察、observe()与observeForever()的区别、LiveData的生命周期感知特性
好,咱们今天来聊聊LiveData。说实话,这个组件是我在项目里用得最频繁的之一。它不像某些框架那么花哨,但胜在简单、可靠。你想想看,在Android开发中,数据从后台线程跑到UI线程,还要考虑Activity、Fragment的生命周期,稍不留神就出问题。LiveData就是来解决这个痛点的。
3.1 LiveData是什么?
LiveData,说白了就是一个可观察的数据持有者。它跟普通的Observable最大的区别在于——它知道Activity、Fragment、Service这些组件的生命周期状态。
我刚开始接触时,觉得它就是个包装类。用久了才发现,它的生命周期感知能力才是真正的杀手锏。
核心特性:
- 数据驱动UI更新
- 自动感知生命周期
- 不会发生内存泄漏
- 配置变更时自动恢复数据
3.2 创建LiveData
创建LiveData其实很简单。最常用的方式就是使用MutableLiveData,它提供了setValue()和postValue()两个方法来更新数据。
// 创建一个LiveData,持有String类型的数据
val userName: MutableLiveData<String> = MutableLiveData()
// 设置初始值
userName.value = "默认用户"
// 更新数据(必须在主线程)
userName.setValue("张三")
// 更新数据(可以在后台线程)
userName.postValue("李四")
嗯,这里要注意一点。setValue()只能在主线程调用,而postValue()可以在任何线程调用,它会自动把更新操作post到主线程去执行。
我在项目中遇到过一个问题:连续调用postValue()两次,只有最后一次生效。为什么?因为postValue()内部是使用Handler来post任务的,如果两次post间隔太短,前一个任务还没执行就被后一个覆盖了。所以如果你需要保证每次更新都生效,建议用setValue()。
3.3 观察LiveData
观察LiveData有两种方式:observe()和observeForever()。这两个方法看起来差不多,但行为天差地别。
3.3.1 observe()——生命周期感知的观察
val liveData: MutableLiveData<String> = MutableLiveData()
// 在Activity或Fragment中观察
liveData.observe(this, Observer { value ->
// 当数据变化时,这里会被回调
textView.text = value
})
这里的this就是LifecycleOwner。LiveData会监听这个Owner的生命周期状态:
- 当Owner处于STARTED或RESUMED状态时,Observer是活跃的,能收到数据更新
- 当Owner处于DESTROYED状态时,Observer会被自动移除
- 当Owner从后台回到前台时,Observer会自动重新激活
说白了,你完全不用操心取消注册的事。LiveData帮你搞定了。
3.3.2 observeForever()——永久的观察
val observer = Observer<String> { value ->
// 不管生命周期如何,都会收到回调
Log.d("TAG", "收到数据: $value")
}
// 注册永久观察者
liveData.observeForever(observer)
// 记得在不需要时手动移除
liveData.removeObserver(observer)
看到区别了吗?observeForever()不会感知生命周期。一旦注册,只要LiveData有数据变化,它就会回调。哪怕Activity已经销毁了,它依然会执行。
我曾经踩过的坑:
有一次我在一个Fragment里用了observeForever(),但忘记在onDestroy()里调用removeObserver()。结果Fragment销毁后,Observer还在,导致内存泄漏。更糟糕的是,数据更新时回调里还在操作已经销毁的View,直接Crash。
所以,用observeForever()一定要成对出现:注册和移除。
3.4 observe()与observeForever()的区别
我整理了一张对比表,方便你快速理解:
| 对比项 | observe() | observeForever() |
|---|---|---|
| 需要LifecycleOwner | 是 | 否 |
| 生命周期感知 | 是,自动管理 | 否,需要手动管理 |
| 自动移除 | 是,Owner销毁时自动移除 | 否,必须手动调用removeObserver() |
| 内存泄漏风险 | 低 | 高(如果忘记移除) |
| 适用场景 | Activity/Fragment中更新UI | 后台服务、全局监听等 |
我个人习惯是:能用observe()绝不用observeForever()。只有在确实需要全局监听、且能保证手动管理生命周期的情况下,才考虑后者。
3.5 LiveData的生命周期感知特性
这个特性是LiveData的精髓。咱们来深入看看它是怎么工作的。
LiveData内部维护了一个LifecycleRegistry,它会监听LifecycleOwner的状态变化。当Owner的状态变为DESTROYED时,LiveData会自动清理Observer。当Owner从后台回到前台时,LiveData会重新激活Observer,并把最新的数据推送过去。
你想想看,这意味着什么?
- Activity旋转时,数据不会丢失
- Activity在后台时,不会浪费资源去更新UI
- Activity销毁时,不会发生内存泄漏
我曾经接手过一个项目,里面用Callback来更新UI。Activity旋转后,旧的Callback还在,新的Callback又注册了,结果数据更新时UI被更新了两次,还出现了空指针。后来改成LiveData,这些问题全没了。
小技巧:
如果你需要在Activity后台时也能收到数据更新(比如记录日志),可以用observeForever()。但记得在onDestroy()里移除。或者,你也可以用observe()配合Lifecycle.Event.ON_STOP来做一些特殊处理。
3.6 知识体系总览
下面这张图帮你梳理了LiveData的核心知识点:
3.7 实战建议
最后,给你几个我在实战中总结的建议:
- 优先使用
observe():在Activity、Fragment中,永远用observe()。它最安全,最省心。 - 避免在非UI层持有LiveData的引用:LiveData是给UI层用的。ViewModel里可以持有,但Repository层尽量用Flow或RxJava。
- 注意
postValue()的覆盖问题:如果需要保证每次更新都生效,用setValue()。 - 善用
MediatorLiveData:当你需要合并多个LiveData源时,它比手动监听方便得多。
好了,LiveData的基础就聊到这里。记住一句话:LiveData不是万能的,但没有LiveData是万万不能的。在Android的MVVM架构中,它是最基础、最可靠的一环。