LiveData使用和原理

LiveData使用和原理

本文链接:https://blog.csdn.net/feather_wch/article/details/131797422



要点:

  1. 注册监听+事件分发+生命周期感知
  2. 粘性事件

LiveData使用

1、LiveData不能在子线程putValue,只能postValue

object MyLiveData {
    
    
    val data:MutableLiveData by lazy {
    
     MutableLiveData() }
    init {
    
    
        data.value = "default" // 该单例第一次在子线程中使用,会触发初始化,putValue()会闪退
        // 另一个进程的Service中thread{}中去使用,会出现问题
    }
}

2、后观察数据是什么效果?为什么可以收到之前的数据?

  1. 会收到数据 => 【数据粘性】
  2. 一般动态修改LiveData源码,避免数据粘性

3、怎么修改数据粘性?

  1. Hook,反射,动态修改源码

4、LiveData简单使用

  1. 创建一个 LiveData 对象并提供一个初始值:
val data = MutableLiveData()
data.value = "Hello LiveData"
  1. 在观察者中订阅 LiveData 对象以接收数据的更新:
data.observe(this, Observer {
    
     value ->
    // 在这里处理数据更新的逻辑
    println(value)
})

5、在 ViewModel 中使用 LiveData:

class MyViewModel : ViewModel() {
    
    
    private val _data = MutableLiveData()
    val data: LiveData get() = _data // 将其转换为不可变的 LiveData 对象 `data`
    fun fetchData() {
    
    
        // 模拟从网络或数据库获取数据
        val newData = "New Data"
        _data.value = newData // Activity 或 Fragment 可以通过观察 `data` 来接收数据的更新。
    }
}

Transformations

6、使用 Transformations.map 转换 LiveData:Int->String

// 转换:添加内容返回新的LiveData对象
val data: LiveData = Transformations.map(sourceData) {
    
     input ->
    "Transformed: $input"
}

7、数据排序:当你从数据库或网络获取到未排序的数据列表时,你可以使用 Transformations.map 来将其排序成一个有序的列表:

val unsortedListLiveData: LiveData<List> = ...
val sortedListLiveData: LiveData<List> = Transformations.map(unsortedListLiveData) {
    
     unsortedList ->
    unsortedList.sorted()
}

、数据过滤:当你需要根据特定条件筛选出符合条件的数据时,你可以使用 Transformations.map 来进行数据过滤:

val originalLiveData: LiveData<List> = ...
val filteredLiveData: LiveData<List> = Transformations.map(originalLiveData) {
    
     originalList ->
    originalList.filter {
    
     it.startsWith("A") } // 只保留以字母 "A" 开头的元素
}

LiveData相关类

1、LiveData:

  1. LiveData 是一个抽象类,用于定义可观察的数据持有者。
  2. 它具有生命周期感知能力,可以自动保证数据更新时只在活跃的观察者中进行通知。

2、MutableLiveData:

  1. MutableLiveData 是 LiveData 的子类,可以更改持有的数据。
  2. 它提供了 setValue() 和 postValue() 方法,用于更新 LiveData 中的值。通常用于作为可观察的数据源。

3、MediatorLiveData:

  1. MediatorLiveData 是 MutableLiveData 的子类,可以合并多个 LiveData 对象,并在其中一个 LiveData 发生更改时通知观察者。

4、Transformations:

  1. Transformations 是一个工具类,提供了一些转换函数,用于对 LiveData 进行转换操作,如 map()、switchMap()、filter() 等。

5、Observer:

  1. Observer 是一个函数接口(SAM 接口-单个抽象方法),用于定义观察者的操作逻辑。
  2. 通常可以使用 lambda 表达式、匿名内部类或 ViewModel 中的引用来实现 Observer 接口。

6、LifecycleOwner:LifecycleOwner 是一个接口,表示具有生命周期感知能力的组件,如 Activity、Fragment。LiveData 可以感知 LifecycleOwner 的生命周期,自动管理观察者的注册和注销。

7、SAM单个抽象方法,类似有Runnable

public interface Observer {
    
    
    void onChanged(T t);
}

8、LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver

  1. 是LiveData内部的辅助类
  2. LifecycleOwner销毁时,取消订阅
  3. LifecycleOwner处于活动状态(STARTED和RESUMED)会调用onActive()告诉外界活动中
  4. LifecycleOwner处于非活动状态(STOPPED和DESTROYED),会调用onInactive()告诉外界非活动
  5. 可以避免浪费资源或内存泄漏。

原理

1、注册监听流程

MutableLiveData("String").observe(this){
    
    it}
#LiveData
observe(LifecycleOwner owner, Observer observer)
  ->assertMainThread("observe");
  if (owner.getLifecycle().getCurrentState() == DESTROYED) return; // 1. 销毁,无反应,避免内存泄漏
  ->LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);// 2. 包装成真正的观察者,去感知Lifecycle
  ->ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);  // 3. SafeIterableMap,线程安全Map,不存在添加,存在则取出
  ->owner.getLifecycle().addObserver(wrapper); // 4. 注册监听,生命周期

2、感知Lifecycle生命周期

  1. 生命周期改变–>判断–>dispatchingValue()分发数据
LifecycleBoundObserver.onStateChanged() 会感受到生命周期变化
 ->DESTROYED => removeObserver(mObserver);
 ->activeStateChanged(shouldBeActive());
  ->dispatchingValue(ObserverWrapper)
    ->for()遍历
      ->considerNotify()
        ->if (observer.mLastVersion >= mVersion) return; // 粘性事件
        ->observer.mObserver.onChanged((T) mData); // 传输数据给观察者

3、事件分发:postValue、setValue

#LiveData
->assertMainThread("setValue");
->mVersion++; // 发一次事件,版本号+1
->mData = value;
->dispatchingValue(null);
  ->for()遍历
    ->considerNotify()
      ->if (observer.mLastVersion >= mVersion) return; // 粘性事件
      ->observer.mObserver.onChanged((T) mData); // 传输数据给观察者

粘性事件

4、observer.mLastVersion和mVersion

  1. mVersion:每次数据更新时++
  2. observer.mLastVersion表示上次观察者接收到的版本号。// = mVersion
  3. observer.mLastVersion >= mVersion:观察者已经接收过相同版本的数据,直接返回,避免重复处理相同的数据。

5、为什么会有粘性事件

  1. 新建观察者 mLastVersion = START_VERSION = -1
  2. 会收到LiveData的最新数据
  3. 不是BUG,默认有粘性,用户可以自主解决粘性问题

6、如何解决粘性事件

  1. 反射让observer.mLastVersion、mVersion相等
  2. UnPeekLiveData版本:自己模拟mVersion和Observer的mLastVersion,在onChanged()判断是否交给外界Observer。
  3. LiveData数据恢复时,也会恢复咱们自定义的mVersion,系统调用LiveData的observe()重新构建实例是用的是这个恢复后的mVersion作为模拟的mLastVersion
  4. 官方SingleLiveData:不支持多个观察者

数据倒灌

7、什么是数据倒灌?本质就是粘性事件,新造了名词。

  1. 下面总结:本质还是在LiveData有数据后,observe()会接收到上一次数据。
  2. Activity异常销毁然后重建,ViewModel中的Livedata会保存之前数据包括mVersion
  3. Activity重建后会调用LiveData的observe(),内部会重新new一个实例,会将mLastVersion恢复到初始值。
  4. observe()->addObserver()->注册生命周期监听,就会触发生命周期回调,就会分发事件dispatchingValue()判断版本号

问题思考

1、LiveData在多线程中是如何处理的?
2、为什么要有MutableLiveData而不是直接使用LiveData?体现了什么原则?

  1. 开闭原则
  2. LiveData内部非常庞大复杂,MutableLiveData对扩展开放,对修改关闭

设计模式

1、LiveData的模板方法模式:onActive、onInactive
2、外观模式:MutableLiveData隐藏了LiveData内部的复杂子系统,注册监听、生命周期感知、事件分发

自己实现KT版本LiveDataBusKt

猜你喜欢

转载自blog.csdn.net/feather_wch/article/details/131797422
今日推荐