优化livedata数据倒灌
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
package com.ttstd.dialer.livedata;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.MainThread;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解决一次性事件的数据倒灌问题,仅通知一次观察者
|
||||||
|
*/
|
||||||
|
public class SingleLiveEvent<T> extends MutableLiveData<T> {
|
||||||
|
private static final String TAG = "SingleLiveEvent";
|
||||||
|
private final AtomicBoolean mPending = new AtomicBoolean(false); // 标记事件是否待处理
|
||||||
|
|
||||||
|
@MainThread
|
||||||
|
@Override
|
||||||
|
public void observe(androidx.lifecycle.LifecycleOwner owner, final Observer<? super T> observer) {
|
||||||
|
// 警告:多个观察者同时注册时,只有一个会收到通知
|
||||||
|
if (hasActiveObservers()) {
|
||||||
|
Log.w(TAG, "多个观察者注册,但仅第一个会收到事件");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 包装观察者,仅在事件未处理时触发
|
||||||
|
super.observe(owner, t -> {
|
||||||
|
if (mPending.compareAndSet(true, false)) { // 原子操作:如果是true则改为false,并返回true
|
||||||
|
observer.onChanged(t); // 触发观察者回调
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainThread
|
||||||
|
@Override
|
||||||
|
public void setValue(T value) {
|
||||||
|
mPending.set(true); // 标记事件待处理
|
||||||
|
super.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简化Void类型事件的调用(如无参数的事件)
|
||||||
|
*/
|
||||||
|
@MainThread
|
||||||
|
public void call() {
|
||||||
|
setValue(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.ttstd.dialer.livedata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包装数据和版本号,用于版本校验
|
||||||
|
*/
|
||||||
|
public class VersionedData<T> {
|
||||||
|
private final T data; // 实际数据
|
||||||
|
private final int version; // 数据版本号
|
||||||
|
|
||||||
|
public VersionedData(T data, int version) {
|
||||||
|
this.data = data;
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.ttstd.dialer.livedata;
|
||||||
|
|
||||||
|
import androidx.annotation.MainThread;
|
||||||
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过版本号控制数据消费,避免旧数据倒灌
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带版本控制的LiveData,解决数据倒灌问题
|
||||||
|
*/
|
||||||
|
public class VersionedLiveData<T> extends LiveData<VersionedData<T>> {
|
||||||
|
private int currentVersion; // 数据版本号(初始化为0)
|
||||||
|
|
||||||
|
// 修正:父类构造器直接使用初始版本0,避免引用未初始化的currentVersion
|
||||||
|
public VersionedLiveData() {
|
||||||
|
super(new VersionedData<>(null, 0)); // 初始数据版本为0
|
||||||
|
this.currentVersion = 0; // 初始化版本号(与父类初始数据一致)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修正:改名避免与父类setValue冲突(父类setValue参数为VersionedData<T>)
|
||||||
|
* 更新数据并自动递增版本号
|
||||||
|
*/
|
||||||
|
@MainThread
|
||||||
|
public void setNewValue(T newValue) {
|
||||||
|
currentVersion++; // 版本号递增
|
||||||
|
// 调用父类的setValue,传入包装后的带版本数据
|
||||||
|
super.setValue(new VersionedData<>(newValue, currentVersion));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册带版本校验的观察者,仅接收新版本数据
|
||||||
|
*/
|
||||||
|
public void observeWithVersion(LifecycleOwner owner, final VersionedObserver<T> observer) {
|
||||||
|
observe(owner, new Observer<VersionedData<T>>() {
|
||||||
|
private int lastHandledVersion = -1; // 记录上次处理的版本号
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChanged(VersionedData<T> newData) {
|
||||||
|
if (newData == null) return;
|
||||||
|
// 仅处理版本号高于上次的新数据
|
||||||
|
if (newData.getVersion() > lastHandledVersion) {
|
||||||
|
lastHandledVersion = newData.getVersion();
|
||||||
|
observer.onNewData(newData.getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本化观察者接口,用于接收新数据
|
||||||
|
*/
|
||||||
|
public interface VersionedObserver<T> {
|
||||||
|
void onNewData(T data);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user