优化livedata数据倒灌

This commit is contained in:
2025-11-10 20:30:20 +08:00
parent 02772c241e
commit 8e973eb2e2
3 changed files with 130 additions and 0 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}