当前位置:网站首页>LiveData源码赏析三 —— 常见问题
LiveData源码赏析三 —— 常见问题
2022-06-30 10:39:00 【Android每日一讲】
数据丢失
通过postValue()方法更新LiveData数据的时候,可能存在数据丢失的情况。
val liveData = MutableLiveData()
Thread {
for (index in 0..9) {
liveData.postValue("new str $index")
}
}.start()
liveData.observe(this) {
Log.i("LiveData", "observe: $it")
}
我们连续调用了postValue()10次,但是结果只有最后一次的数据。
LiveData: observe: new str 10
这是因为postValue()方法内部其实是将数据回调的逻辑放到了Runnable中,再post给Handler,利用Handler在主线程中更新,因此从postValue()到执行Runnable,中间是存在时间差的。在这段时间内通过postValue()方法更新数据仅仅会改变LiveData内部的值,而不会再次post一个新的Runnable。
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
只有当Runnable被执行了mPendingData才会被赋值为NOT_SET,这样在postValue()的时候执行postTask = mPendingData == NOT_SET才会让postTask的值为true,最后才会post一个Runnable。
粘性事件
发射的事件如果早于注册,那么注册之后依然可以接收到的事件称为粘性事件。
LiveData内部是通过一个整数mVersion来记录当前数据的版本号。
protected void setValue(T value) {
//省略其他代码
mVersion++;
}
当我们调用setValue()更新数据的时候,mVersion就会自增。
private abstract class ObserverWrapper {
int mLastVersion = -1;
}
在我们的观察者的包装类ObserverWrapper内部也维护了一个版本号mLastVersion,它记录的是上一次回调的数据的版本,初始化为-1。
如果我们先改变LiveData的数据,那么mVersion就会自增变为1,然后注册观察者,此时观察者内部维护的版本号mLastVersion为初始值-1。最后在回调判断的时候(observer.mLastVersion >= mVersion)就会不成立,从而观察者就会收到它注册之前的数据。
private void considerNotify(ObserverWrapper observer) {
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
数据处理
如果希望在将 LiveData 对象分派给观察者之前对存储在其中的值进行更改,或者需要根据另一个实例的值返回不同的 LiveData 实例,可以使用Transformations类来进行LiveData的数据处理。
map
map可以将LiveData内部的数据类型转换,使LiveData转换为LiveData。
val intLiveData = MutableLiveData(1)
val strLiveData:LiveData<String> = Transformations.map(intLiveData){
"$it"
}
strLiveData.observe(this){
println(it is String)//true
}
switchMap
switchMap()可以根据某个值,切换观察不同的LiveData数据。也可以实现LiveData转换为LiveData。
val originLiveData = MutableLiveData(true)
val trueLiveData = MutableLiveData("trueLiveData")
val falseLiveData = MutableLiveData("falseLiveData")
val distinctLiveData = Transformations.switchMap(originLiveData) {
if (it) {
trueLiveData
} else {
falseLiveData
}
}
distinctLiveData.observeForever {Log.i(TAG, it)}//trueLiveData
distinctUntilChanged
distinctUntilChanged()方法返回一个屏蔽了原始LiveData重复数据的新LiveData。
val boolLiveData = MutableLiveData<Boolean>()
val distinctLiveData = Transformations.distinctUntilChanged(boolLiveData)
Thread {
for (index in 0..10) {
SystemClock.sleep(100)
boolLiveData.postValue((index < 9))
}
}.start()
distinctLiveData.observe(this){
println(it) //结果去重了 只有true 和 false 两个输出
}
感知生命周期
LiveData.observer()方法可以感知Owner的生命周期,在调用此方法的时候会传入一个LifecycleOwner对象,LifecycleOwner是一个接口。
public interface LifecycleOwner {
Lifecycle getLifecycle();
}
Fragment和FragmentActivity都实现了此接口并返回一个LifecycleRegistry对象,当他们生命周期发生变化的时候,会调用LifecycleRegistry.handleLifecycleEvent()方法分发生命周期给对应的生命周期观察者。回调LifecycleEventObserver的onStateChanged()方法。 而LifecycleBoundObserver实现了LifecycleEventObserver接口,所以他能接收到生命周期改变的回调。
public interface LifecycleEventObserver extends LifecycleObserver {
void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
边栏推荐
- Dickinson's soul chooses its companion
- The reasoning delay on iphone12 is only 1.6 MS! Snap et al. Analyzed the transformer structure latency in detail, and used NAS to find out the efficient network structure of mobile devices
- Machine learning interview preparation (I) KNN
- Every time I look at my colleagues' interface documents, I get confused and have a lot of problems...
- LVGL 8.2 Drop down in four directions
- 训练一个图像分类器demo in PyTorch【学习笔记】
- MySQL export SQL script file
- ArrayList与顺序表
- 科普达人丨漫画图解什么是eRDMA?
- LVGL 8.2 Image
猜你喜欢
![[understanding of opportunity -34]: fate is within the light cone](/img/3e/9f5630ba382df7f7ce00705445cef8.jpg)
[understanding of opportunity -34]: fate is within the light cone

数据库什么时候需要使用索引【杭州多测师】【杭州多测师_王sir】

CSDN blog operation team 2022 H1 summary

Sarsa笔记

深潜Kotlin协程(十六):Channel

我们公司使用 7 年的这套通用解决方案,打通了几十个系统,稳的一批!

深潜Kotlin协程(十八):冷热数据流

What is erdma as illustrated by Coptic cartoon?

无心剑中译狄金森《灵魂择其伴侣》

语音识别-基础(一):简介【语音转文本】
随机推荐
Viewing technological changes through Huawei Corps (V): smart Park
LVGL 8.2 Simple Colorwheel
【STL源码剖析】容器(待补充)
[rust daily] the first rust monthly magazine on January 22, 2021 invites everyone to participate
[rust weekly database] num bigint - large integer
20万奖金池!【阿里安全 × ICDM 2022】大规模电商图上的风险商品检测赛火热报名中!...
训练一个图像分类器demo in PyTorch【学习笔记】
pytorch 笔记:validation ,model.eval V.S torch.no_grad
Memory escape analysis
Unity Shader - 踩坑 - BRP 管线中的 depth texture 的精度问题(暂无解决方案,推荐换 URP)
LVGL 8.2 re-coloring
Algorithme leetcode 86. Liste des liens séparés
LVGL 8.2 menu from a drop-down list
[leetcode 16] sum of three numbers
Deep dive kotlin Xie Cheng (17): Actor
The two e-commerce bigwigs' lacy news screens represent the return of e-commerce to normal, which will be beneficial to the real economy
CP2112使用USB转IIC通信教学示例
Pytorch notes torch nn. BatchNorm1d
Qt之实现动效导航栏
The intelligent DNA molecular nano robot model is coming