Jetpack - LiveData

查看最新版本

implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

一、概念

一个可以被观察的数据持有类,LiveData是只读版本,MutableLiveData是可读可写版本,。

  • 用来更新UI:setValue()和postValue()更新值都是在主线程执行,因此观察者的onChange()回调在主线程。
  • 生命周期感知:可以感知 Activity、Fragment或Service 等组件的生命周期,无需手动处理,UI层只需要对数据进行监听。
  • 单个最新值:更新UI需要使用最新数据,过时的数据应该被忽略。并且只会在界面处于活跃状态(onStart和OnResume)收到通知(非活跃状态更新UI无意义浪费资源)。
  • 自动取消订阅:Observers 是绑定到 Lifecycle 对象上的,当与其关联的 lifecycle 被销毁的时候,它们会自动被清理。开发者无需手写模板代码,降低内存泄漏风险。
  • 粘性事件:当按下Button弹出Snackerbar,此时设备配置改变(例如屏幕旋转),之前的View会销毁然后重建,新的View会重新订阅,那么会再次消费事件弹出Snackerbar。
  • 默认不防抖:更新的值和上次相同,onChange()依然会再次调用。可以使用Transformations的distinctUntilChanger()、SingleLiveEvent解决。
observe ( )对LiveData进行观察(订阅)。

oberverForever ( )

无论界面处于什么状态都能收到通知,因此用完一定要记得调用removeObserver()来取消订阅,否则LiveData会一直处于激活状态,Activity永远不会被系统自动回收,这就造成了内存泄漏。
removeObserve ( )移除当前所有观察者。
hasObserve ( )如果有观察者。
hasActiveObserve ( )如果有活跃的观察者(UI处于onStart或者onResume)。
getValue ( )获取数据。
setValue ( )设置数据(主线程中调用)。
postValue ( )设置数据(子线程中调用)。

二、创建

2.1 MutableLiveData

LiveData是只读版本,MutableLiveData是可读可写版本,根据实际需求暴露不同类型收窄功能。没有初始化值默认为null。

ViewModel {
    //权限封装
    private val _num = MutableLiveData<Int>()    //私有化可读可写版本
    val num: LiveData<Int> = _num    //对外暴露只读版本
    //初始化值
    init { 
        viewModelScope.launch {
            _num.value = getData()    //调用挂起函数赋值
        }
    }

    //数据源(Suspend)
    suspend fun getData(): Int = withContext(Dispatchers.IO) { 3 }
    //数据源(Flow)
    val data: Flow<Int> = flow { repeat(3) { emit(it) } }
}

UI {
    viewModel.num.observe(this, Observer { num -> ... })
    viewModel.num.observer(this) { num -> ... }    //ktx写法
}

2.2 MediatorLiveData

继承自MutableLiveData,增加了合并多个LivaData数据源的功能,可以同时监听多个LiveData的数据变化。例如分别为本地和网络两个数据创建LiveData,通过MutableLiveData调用addSource()将两个LiveData数据源添加进去,最后Ovserve即可。

ViewModel {
    val local = MutableLiveData<String>()
    val remote = MutableLiveData<String>()
    val combine = MediatorLiveData<String>()
    combine.addSource(local) { combine.value = it }
    combine.addSource(remote) { combine.value = it }
}
UI {
    viewModel.combine.observe(this, Observe { value ->

    })
}

2.3 Transformations

工作在主线程,对LiveData持有的数据应用函数。

mapLiveData持有的数据信息过多,只需要取其中一部分。例如持有User只需要User.name。
switchMap使用LiveData持有的数据来获取另一个LiveData对象。
distinctUntilChanged更新的值和当前值相同则不会回调onChange()。
//Transformations.map
val userLiveData: LiveData<User> = MutableLiveData(User())
val nameLiveData: LiveData<String> = Transformations.map(userLiveData) { user ->
    user.name
}
//Transformations.switchMap
fun getUser(id: Long): LiveData<User> {...}
val idLiveData: LiveData<Long> = MatableLiveData(123456)
val userLiveData: LiveData<User> = Transformations.switchMap(idLiveData) { id ->
    getUser(id)
}

2.4 Suspend → LiveData(协程构建器)

LifeCycle v2.20 版本后,可以在定义LiveData的同时使用挂起函数的结果赋值(由于只读无法更新,适用于一次性数据),省去了对只读限制的封装,Activity中直接观察ViewModel的该属性。

public fun <T> liveData(
    context: CoroutineContext = EmptyCoroutineContext,//区块所执行的协程上下文,默认+Main.immediate
    timeoutInMs: Long = DEFAULT_TIMEOUT,        //没有观察者后,多少毫秒后取消区块,默认5s
    @BuilderInference block: suspend LiveDataScope<T>.() -> Unit        //区块在LiveData被观察的时候执行
): LiveData<T>
class MyViewModel : ViewModel() {
    //直接调用挂起函数赋值
    val num1 = liveData { emit(getData()) }
    //还可以指定线程,单独写耗时操作
    val num2: LiveData<Int> = liveData(Dispatchers.IO) {
        emit(5)
        delay(1000)
        emit(3)
    }
    //从另一个LivaData获取更新结果
    val aa = MutableLiveData(10)
    val bb = liveData{ emitSource(aa) }
    suspend fun getData(): Int = withContext(Dispatchers.IO) { 3 }
}

2.6 Flow → LiveData(扩展函数)

public fun <T> Flow<T>.asLiveData(
    context: CoroutineContext = EmptyCoroutineContext,//区块所执行的协程上下文,默认+Main.immediate
    timeoutInMs: Long = DEFAULT_TIMEOUT        //没有观察者后,多少毫秒后取消区块,默认5s
): LiveData<T>
class MyViewModel : ViewModel() {
    val num1: LiveData<Int> = liveData { DataSource().getDataFlow.collect { emit(it) } }
    val num2: LiveData<Int> = DataSource().getDataFlow.asLiveData()    //简写
}

class DataSource {
    val getDataFlow: Flow<Int> = flow { repeat(3) { emit(it) } }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值