LiveData源码赏析三 —— 常见问题

数据丢失

通过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);
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LiveData 是用于在 Android 应用程序中观察数据的一个组件。LiveData 是一个可观察的数据持有者类,它具有生命周期感知能力,因此它会自动管理它与 Activity 和 Fragment 生命周期的关系,从而可以避免内存泄漏和崩溃。 LiveData 的一个重要特性是它可以通知观察者数据已更改。当 LiveData 的值发生更改时,它会自动通知所有观察者。这意味着您无需手动更新 UI 或执行其他操作以反映数据更改。LiveData 还支持数据转换和过滤,因此您可以将原始数据转换为 UI 可以直接使用的格式。 LiveData 使用观察者模式进行数据监听,您可以使用 `observe()` 方法将观察者添加到 LiveData 实例中,该方法需要传入一个 LifecycleOwner 和一个 Observer 对象。LifecycleOwner 表示 LiveData 与哪个组件的生命周期绑定,通常是 Activity 或 Fragment。Observer 对象定义了当 LiveData 的值更改时要执行的操作。 下面是一个简单的示例,演示如何使用 LiveData 监听数据更改: ``` // 创建一个 LiveData 实例 val myLiveData = MutableLiveData<String>() // 将观察者添加到 LiveData 实例中 myLiveData.observe(this, Observer { newValue -> // 在这里更新 UI 或执行其他操作 textView.text = newValue }) // 更改 LiveData 的值 myLiveData.value = "Hello World" ``` 在上面的示例中,我们创建了一个名为 `myLiveData` 的 LiveData 实例,并将其与当前组件的生命周期绑定。我们还将一个 Observer 对象传递给 `observe()` 方法,以便在 LiveData 的值更改时执行操作。当我们调用 `myLiveData.value = "Hello World"` 时,LiveData 会自动通知所有观察者,以便更新 UI 或执行其他操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值