LiveData 粘性事件解决方案 附:简易LiveDataBus

本文介绍了针对LiveData的粘性事件解决方案,探讨了如何在Android应用中实现粘性事件传递,并附带了一个简单的LiveDataBus实现,用于增强LiveData的功能。

LiveData 粘性事件解决方案

**LiveData源码分析**
private void considerNotify(LiveData.ObserverWrapper observer) {
   
   
        if (!observer.mActive) {
   
   
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
        //
        // we still first check observer.active to keep it as the entrance for events. So even if
        // the observer moved to an active state, if we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
   
   
            observer.activeStateChanged(false);
            return;
        }

        //上面的判断是生命周期的拦截
        //一般事件流程 :new Observe(mVersion=-1)-> 注册观察者(mLastVersion=-1)-> setValue(mVersion++) 
        //粘性事件的流程 :new Observe(mVersion=-1)-> setValue(mVersion++) ->注册观察者(mLastVersion=-1)
        //此时 mLastVersion=-1 , mVersion=0 ,未触发拦截导致首次注册时会触发接口回调造成粘性事件
        if (observer.mLastVersion >= mVersion) {
   
   
            
处理LiveData粘性事件通常可以采用以下几种方法: #### 重写LiveData的方法(Hook方式) 为了使 `mLastVersion >= mVersion`,可以重写LiveData中的方法,这就需要用到Hook。通过反射机制修改LiveData内部的状态,从而避免粘性事件的发生。以下是一个简单的示例代码: ```kotlin import androidx.lifecycle.LiveData import androidx.lifecycle.Observer import java.lang.reflect.Field import java.lang.reflect.Method class NonStickyLiveData<T> : LiveData<T>() { override fun observe(owner: androidx.lifecycle.LifecycleOwner, observer: Observer<in T>) { super.observe(owner, observer) try { // 获取LiveData的mObservers字段 val observersField: Field = LiveData::class.java.getDeclaredField("mObservers") observersField.isAccessible = true val observers = observersField.get(this) // 获取SafeIterableMap的get方法 val methodGet: Method = observers.javaClass.getDeclaredMethod("get", Any::class.java) methodGet.isAccessible = true val entry = methodGet.invoke(observers, observer) // 获取ObserverWrapper的mLastVersion字段 if (entry != null) { val observerWrapperClass = entry.javaClass.superclass val lastVersionField: Field = observerWrapperClass!!.getDeclaredField("mLastVersion") lastVersionField.isAccessible = true // 获取LiveData的mVersion字段 val versionField: Field = LiveData::class.java.getDeclaredField("mVersion") versionField.isAccessible = true val version = versionField.get(this) // 设置mLastVersion等于mVersion lastVersionField.set(entry, version) } } catch (e: Exception) { e.printStackTrace() } } } ``` 使用时,将原来的 `LiveData` 替换为 `NonStickyLiveData`: ```kotlin val nonStickyLiveData = NonStickyLiveData<String>() nonStickyLiveData.observe(this, Observer { value -> // 处理数据 }) ``` #### 使用SingleLiveEvent `SingleLiveEvent` 是一种特殊的 `LiveData`,它只能发送一次事件,发送后会自动重置,从而避免粘性事件。以下是一个简单的 `SingleLiveEvent` 实现: ```kotlin import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer import java.util.concurrent.atomic.AtomicBoolean class SingleLiveEvent<T> : MutableLiveData<T>() { private val mPending = AtomicBoolean(false) override fun observe(owner: androidx.lifecycle.LifecycleOwner, observer: Observer<in T>) { super.observe(owner, Observer { t -> if (mPending.compareAndSet(true, false)) { observer.onChanged(t) } }) } override fun setValue(t: T?) { mPending.set(true) super.setValue(t) } override fun postValue(value: T?) { mPending.set(true) super.postValue(value) } } ``` 使用时: ```kotlin val singleLiveEvent = SingleLiveEvent<String>() singleLiveEvent.observe(this, Observer { value -> // 处理数据 }) singleLiveEvent.value = "新数据" ``` #### 使用第三方库 除了手动实现,还可以使用一些第三方库来处理粘性事件,例如 `LiveEvent` 库,它提供了更方便的方式来处理 `LiveData` 的粘性问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值