一、LiveData简介
1、LivaData是什么?
LiveData 是一种具有生命周期(如 Activity、Fragment 或 Service)感知能力的、可观察的数据存储器类。LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
2、LivaData的优势
2-1:LiveData能确保UI和数据状态相符
LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知 Observer 对象来更新界面。
2-2:不会发生内存泄漏
观察者和Lifecycle对象绑定,能在销毁时自动解除注册
2-3:不会给已经停止的Activity发送事件
如果观察者处于非活跃状态,LiveData不会再发送任何事件给这些Observer对象
2-4:不再需要手动处理生命周期
UI组件仅仅需要对相关数据进行观察,LiveData自动处理生命周期状态改变后,需要处理的代码。
2-5:数据始终保持最新状态
一个非活跃的组件进入到活跃状态后,会立即获取到最新的数据,不用担心数据问题
2-6:LiveData在横竖屏切换等Configuration改变时,也能保证获取到最新数据
例如Acitivty、Fragment因为屏幕选装导致重建, 能立即接收到最新的数据
2-7:LiveData能资源共享
如果将LiveData对象扩zhan,用单例模式将系统服务进行包裹。这些服务就可以在app中共享。
3、LiveData的劣势
3-1:LiveData只能在主线程转换更新数据
postValue也是需要切换到到主线程的,当我们想要更新LiveData对象时,我们会经常更改线程(工作线程→主线程),如果在修改LiveData后又要切换回到工作线程那就更麻烦了
3-2:postValue可能会有丢数据的问题
在一段时间内发送数据的速度 > 接受数据的速度,可能导致数据丢失,LiveData 无法正确的处理这些请求。
3-3:LiveData结构简单就是有意被简化设计,LiveData的操作符也不够强大
面对比较复杂的交互数据流场景时,处理起来比较麻烦。
二、LiveData的使用
MutableLiveData的使用
- 1、在
ViewModel中创建一个实例LiveData来保存某种类型的数据。
class NameViewModel : ViewModel() {
// 创建一个字符串类型的LiveData
val currentNameLiveData: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
// Rest of the ViewModel...
}
- 2、注册观察者
Observer并实现onChanged方法,该方法在LiveData对象持有的数据变化的时候回调,来更新UI
class NameActivity : AppCompatActivity() {
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
private val model: NameViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Other code to setup the activity...
// 为LiveData注册Observer观察者
model.currentNameLiveData.observe(this, object : Observer<String>{
override fun onChanged(newName: String?) {
// Update the UI,
nameTextView.text = newName
}
})
}
}
- 3、更新
LiveData对象
button.setOnClickListener {
val anotherName = "Hello"
model.currentNameLiveData.setValue(anotherName)
}
注意点,LiveData建议封装在ViewModel内部使用:
- 避免造成Activity和Fragment的臃肿。现在这些 UI 控制器负责显示数据但不保存数据状态。
- 将
LiveData实例与特定Activity和Fragment实例分离,从而确保LiveData对象在横竖屏切换后继续存在。
LiveData的数据转换
- 1、
Transformations.mapmap函数:基于原LiveData,对其值进行改变然后生成一个新的LiveData返回
api:
/**
* @param source:用于转换的LiveData原始对象
* @param mapFunction: 转换函数
*/
public static LiveData<Y> map (LiveData<X> source, Function<X, Y> mapFunction)
示例:
data class User(val firstName:String,val lastName:String){}
val userLiveData: MutableLiveData<User> by lazy{
MutableLiveData<User>(User("三","张"))
}
// 传入MutableLiveData<User>(User("三","张")) -> MutableLiveData<String>(”张三“)
val userName: MutableLiveData<String> = Transformations.map(userLiveData) {
user -> "${user.lastName} ${user.firstName}"
}
- 2、
Transformations.switchMap()switchMap()函数: 传入LiveData对象,当此LivaData中值变化时,调用转换函数生成新的LiveData对象返回。
api:
/**
* @param source:传入待观察的LiveData对象
* @param switchMapFunction: 转换函数
*/
public static LiveData<Y> switchMap (LiveData<X> source, Function<X,LiveData<Y>> switchMapFunction)
示例:
// 条件结果liveDataA
val liveDataA = MutableLiveData<String>("1001")
// 条件结果liveDataB
val liveDataB = MutableLiveData<String>("2002")
// 条件LiveData
val liveDataSwitch = MutableLiveData<Boolean>(false)
// Transformations.switchMap 监测liveDataSwitch值的变化,条件触发不同的liveData返回
val transformSwitchedLiveData =
Transformations.switchMap(liveDataSwitch) {
switchToB ->
if(switchToB) { liveDataB }
else{ liveDataA }
}
// 注册监听
transformSwitchedLiveData.observe(this,Observer<String> { value ->
value?.let {
txt_fragment.text = it
}
})
// SwitchCompat 开关手动控制liveDataSwitch值的变化
liveDataSwitch.value = switch_live_data.isChecked
switch_live_data.setOnCheckedChangeListener { buttonView, isChecked ->
liveDataSwitch.value = isChecked
}
MediatorLiveData的使用
MediatorLiveData可以作为中介观察或调度多个 LiveData 数据源- 同时也可以做为一个liveData,被其他Observer观察
示例
- 监听多个不同类型数据源,
map()和switchMap()也应用了MediatorLiveData中介功能
// String 类型的liveData
private val liveData1 = MutableLiveData<String>()
// Int类型的liveData
private val liveData2 = MutableLiveData<Int>()
fun setData1(name: String) {
liveData1.value = name
}
fun setData2(id: Int) {
liveData2.value = id
}
val mediatorLiveData = MediatorLiveData<String>()
init {
mediatorLiveData.addSource(liveData1) {
mediatorLiveData.value = "A:$it"
}
mediatorLiveData.addSource(liveData2) {
mediatorLiveData.value = "B:$it"
}
}
// 监听不同数据源更新UI
mediatorLiveData.observe(this, changeObserver)
private val changeObserver = Observer<String> { value ->
value?.let {
text = it
}
}
使用多个MutableLiveData 单独观察数据,更新UI也能实现以上功能,但MutableLiveData需要分别要设置 LifecycleOwner 而 MediatorLiveData 能统一管理添加到它内部所有 LiveData 的生命周期, MediatorLiveData 重写了 LiveData 的 onActive 和 onInactive 方法统一去添加和移除它内部 LiveData 的 Observer
可用点
- MediatorLiveData监听不同来源(缓存、内置、网络)LiveData,更新UI数据