1、什么是 LiveData
答案
LiveData 是可观察、生命周期感知的数据持有者;
能存储单个数据,可被观察者监听,自动感知 Activity/Fragment 生命周期,只给前台活跃页面发数据,页面销毁自动解绑,天然防内存泄漏。
2、LiveData 优点
答案
- 生命周期感知,自动防内存泄漏;
- 页面销毁自动移除观察者,避免空指针;
- 数据粘性,页面重建自动恢复最新数据;
- 不用手动管理注册和解绑,简化代码。
3、LiveData 和 MutableLiveData 区别
答案
- LiveData:只读,只能观察,不能修改值;
- MutableLiveData:继承 LiveData,可读可改,有
setValue()、postValue();开发规范:ViewModel 暴露 LiveData,内部用 MutableLiveData,对外隐藏修改权限。
4、setValue 和 postValue 区别
答案
- setValue:主线程调用,直接赋值;
- postValue:子线程调用,抛到主线程更新;多次连续 postValue 可能只保留最后一次值。
5、LiveData 为什么不会内存泄漏
答案
底层依赖 Lifecycle,感知页面生命周期;
页面进入 DESTROYED 状态,LiveData 自动主动移除观察者,不再持有页面引用,杜绝泄漏。
6、LiveData 粘性事件是什么
答案
新观察者注册后立马收到当前最新值,就算数据先更新、后订阅也能拿到;
场景:屏幕重建自动恢复数据;
弊端:需要单次弹窗、单次跳转时会重复触发,需要防粘性处理。
7、怎么解决 LiveData 粘性事件
答案
- Event 包装类 封装事件,消费过后标记已处理;
- SingleLiveData 自定义只发一次事件;
- 使用 SharedFlow 替代 LiveData 做单次事件。
8、LiveData 能不能背压、适合做流式吗
答案
不适合。
LiveData 适合状态常驻(页面数据、UI 状态);
不适合频繁连续事件、按钮点击、信息流,这类用 Kotlin Flow / SharedFlow。
9、LiveData 原理简单说
答案
基于 Lifecycle 感知页面状态;观察者绑定生命周期,只有页面处于 RESUMED 活跃状态 才分发数据;
页面销毁自动解绑,数据变化主动回调给观察者。
10、多个 Fragment 怎么通过 LiveData 通信
答案
共享同一个 ViewModel,ViewModel 里放 LiveData;
多个 Fragment 观察同一个 LiveData,数据一变全部自动回调,解耦通信。
11、什么是 LiveData 数据倒灌
新页面 / 重建页面 注册观察 LiveData 时,会立马收到上一次旧的历史数据,不是本次新推送的,导致页面重复弹窗、重复请求、页面状态错乱,这就是数据倒灌。
##1 2、为什么会出现倒灌
- LiveData 粘性特性:会缓存最后一次的值;
- 新观察者一订阅,立刻把缓存旧值回调给你;
- 页面横竖屏重建、返回页面重新监听,都会触发旧值补发,造成业务重复执行。
13、常见危害
重复弹窗、重复网络请求、页面状态错乱、事件被多次消费。
14、解决方案(面试必说 4 种)
- Event 事件包装类把数据包一层,用已消费标记,消费过就不再处理,最常用。
- SingleLiveEvent只能发送一次、只能接收一次,避免多次回调;缺点不支持多观察者。
- 使用 SharedFlow / StateFlow 替代Flow 可以配置 replay=0 不回放历史,从根源杜绝粘性倒灌,新项目首选。
- 判断页面状态 / 手动拦截记录页面是否就绪,非就绪状态收到旧值直接丢弃。
- 内部用
mVersion+ 自定义标记局部刷新,或者不往 LiveData 正式存业务事件,就能规避倒灌
15、面试一句话总结
LiveData 数据倒灌是因为它默认粘性缓存最后一次数据,新观察者订阅时会补发旧值,造成重复业务逻辑执行;常用解决方式是Event 包装类、SingleLiveEvent、改用 Flow 设置不回放历史。
面试一句话终极总结
LiveData 是生命周期感知的可观察数据容器,自动绑定 Lifecycle,只给前台活跃页面分发数据,页面销毁自动解绑防泄漏;区分 MutableLiveData 可修改、LiveData 只读;有粘性特性适合 UI 状态保存,不适合一次性事件,一次性事件可用事件包装类或 Flow 替代。