LiveData使用和原理
本文链接:https://blog.csdn.net/feather_wch/article/details/131797422
文章目录
- LiveData使用和原理
- LiveData使用
- Transformations
- LiveData相关类
- 原理
- 粘性事件
- 数据倒灌
- 问题思考
- 设计模式
要点:
- 注册监听+事件分发+生命周期感知
- 粘性事件
LiveData使用
1、LiveData不能在子线程putValue,只能postValue
object MyLiveData {val data:MutableLiveData by lazy { MutableLiveData() }init {data.value = "default" // 该单例第一次在子线程中使用,会触发初始化,putValue()会闪退// 另一个进程的Service中thread{}中去使用,会出现问题}
}
2、后观察数据是什么效果?为什么可以收到之前的数据?
- 会收到数据 => 【数据粘性】
- 一般动态修改LiveData源码,避免数据粘性
3、怎么修改数据粘性?
- Hook,反射,动态修改源码
4、LiveData简单使用
- 创建一个 LiveData 对象并提供一个初始值:
val data = MutableLiveData()
data.value = "Hello LiveData"
- 在观察者中订阅 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:
- LiveData 是一个抽象类,用于定义可观察的数据持有者。
- 它具有生命周期感知能力,可以自动保证数据更新时只在活跃的观察者中进行通知。
2、MutableLiveData:
- MutableLiveData 是 LiveData 的子类,可以更改持有的数据。
- 它提供了 setValue() 和 postValue() 方法,用于更新 LiveData 中的值。通常用于作为可观察的数据源。
3、MediatorLiveData:
- MediatorLiveData 是 MutableLiveData 的子类,可以合并多个 LiveData 对象,并在其中一个 LiveData 发生更改时通知观察者。
4、Transformations:
- Transformations 是一个工具类,提供了一些转换函数,用于对 LiveData 进行转换操作,如 map()、switchMap()、filter() 等。
5、Observer:
- Observer 是一个函数接口(SAM 接口-单个抽象方法),用于定义观察者的操作逻辑。
- 通常可以使用 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
- 是LiveData内部的辅助类
- LifecycleOwner销毁时,取消订阅
- LifecycleOwner处于活动状态(STARTED和RESUMED)会调用
onActive()
告诉外界活动中 - LifecycleOwner处于非活动状态(STOPPED和DESTROYED),会调用
onInactive()
告诉外界非活动 - 可以避免浪费资源或内存泄漏。
原理
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生命周期
- 生命周期改变–>判断–>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
mVersion
:每次数据更新时++observer.mLastVersion
表示上次观察者接收到的版本号。// = mVersionobserver.mLastVersion >= mVersion
:观察者已经接收过相同版本的数据,直接返回,避免重复处理相同的数据。
5、为什么会有粘性事件
- 新建观察者 mLastVersion = START_VERSION = -1
- 会收到LiveData的最新数据
- 不是BUG,默认有粘性,用户可以自主解决粘性问题
6、如何解决粘性事件
- 反射让observer.mLastVersion、mVersion相等
- UnPeekLiveData版本:自己模拟mVersion和Observer的mLastVersion,在onChanged()判断是否交给外界Observer。
- LiveData数据恢复时,也会恢复咱们自定义的mVersion,系统调用LiveData的observe()重新构建实例是用的是这个恢复后的mVersion作为模拟的mLastVersion
- 官方SingleLiveData:不支持多个观察者
数据倒灌
7、什么是数据倒灌?本质就是粘性事件,新造了名词。
- 下面总结:本质还是在LiveData有数据后,observe()会接收到上一次数据。
- Activity异常销毁然后重建,ViewModel中的Livedata会保存之前数据包括mVersion
- Activity重建后会调用LiveData的observe(),内部会重新new一个实例,会将mLastVersion恢复到初始值。
- observe()->addObserver()->注册生命周期监听,就会触发生命周期回调,就会分发事件dispatchingValue()判断版本号
问题思考
1、LiveData在多线程中是如何处理的?
2、为什么要有MutableLiveData而不是直接使用LiveData?体现了什么原则?
- 开闭原则
- LiveData内部非常庞大复杂,MutableLiveData对扩展开放,对修改关闭
设计模式
1、LiveData的模板方法模式:onActive、onInactive
2、外观模式:MutableLiveData隐藏了LiveData内部的复杂子系统,注册监听、生命周期感知、事件分发
自己实现KT版本LiveDataBusKt