📅  最后修改于: 2023-12-03 15:38:12.333000             🧑  作者: Mango
在 Android 开发中,我们常常需要在不同的组件之间传递数据,例如 Activity 和 Fragment 之间、ViewModel 和 View 之间等。在传递数据的过程中,我们经常会遇到重复执行问题,即同一个事件被触发多次。为了解决这个问题,Android 官方推出了 LiveData,但 LiveData 存在一个缺点就是会在界面旋转等场景下重复触发事件。
为了解决 LiveData 的缺点,最近 Google 推荐了一种新的解决方案:SingleLiveEvent。这个类可以在 LiveData 的基础上实现只观察一次事件,避免了 LiveData 重复触发事件的缺点。
SingleLiveEvent 是 LiveData 的子类,继承了 LiveData 的优点,解决了 LiveData 的缺点。SingleLiveEvent 可以实现只接收一次事件的能力。
SingleLiveEvent 的核心思想是记录观察者的状态,以避免对已经活跃的观察者多次分派事件。SingleLiveEvent 具有以下特点:
在 app 模块的 build.gradle 文件中添加如下代码:
dependencies {
implementation 'androidx.lifecycle:lifecycle-livedata:2.2.0'
}
创建一个继承自 LiveData 的 SingleLiveEvent 类,并重写父类的 setValue 和 postValue 方法。
public class SingleLiveEvent<T> extends MutableLiveData<T> {
private final AtomicBoolean mPending = new AtomicBoolean(false);
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
if (hasActiveObservers()) {
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
}
super.observe(owner, new Observer<T>() {
@Override
public void onChanged(T t) {
if (mPending.compareAndSet(true, false)) {
observer.onChanged(t);
}
}
});
}
@MainThread
public void setValue(T t) {
mPending.set(true);
super.setValue(t);
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
public void call() {
setValue(null);
}
}
在需要观察 SingleLiveEvent 的 View 中使用 observe() 方法观察 SingleLiveEvent。
singleLiveEvent.observe(this, new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
//只会回调一次
}
});
在 ViewModel 中声明 SingleLiveEvent 类型的成员变量,并在需要触发事件的地方使用 setValue() 方法触发事件。
public class MainViewModel extends ViewModel {
private SingleLiveEvent<Boolean> mSingleLiveEvent = new SingleLiveEvent<>();
public SingleLiveEvent<Boolean> getSingleLiveEvent() {
return mSingleLiveEvent;
}
public void doSomething() {
//触发事件
mSingleLiveEvent.setValue(true);
}
}
SingleLiveEvent 可以有效地解决 LiveData 在界面旋转等场景下重复触发事件的问题。在大多数场景下,我们建议使用 SingleLiveEvent 来替代 LiveData,以便更好地管理事件的触发。