Android LiveDataBus的使用这里不再赘述,网上有很多关于这个的文章。
网上大部分篇幅采用的hook方式经亲自验证不生效,所以,经过分析,自己使用了另一种方式
目录
1.网上取消黏性事件的方法及实验结果
2.分析网上方式仍然能收到黏性事件的原因
3.怎么解决?
4.LiveDataBus的完整代码为:
5.结语
在Activity中 发射(set)数据,然后 在onResume中延迟3秒后在订阅。NonStickActivityDemo的部分代码为:
LiveDatabus的代码:
试验的结果为:
可以看见 ,即使在发射之后注册观察者,仍然是可以接收上次发送的数据 也就是黏性
仍然能收到黏性事件的原因,关键在于这种方式,在修改Observer的mLastVersion之前调用了super.observe(owner, observer);方法。但是如果不调用super.observe(owner, observer);那么由于此时还没有注册观察者,执行get方法拿出当前观察者对应的对象Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);会返回空。那么,我们来分析下,为什么调用了super.observe(owner, observer);就会接收到黏性数据。来跟踪下源码:
进入super.Observe(owner,observer);也就是LiveData的observe(owner,observer)方法
继续跟进 ,这个方法最后会执行owner.getLifecycle().addObserver(wrapper);这个方法,其中wrapper这个参数,它是一个LifecycleBoundObserver 的实例,来看下LifecycleBoundObserver 的源码:
可以看见,LifecycleBoundObserver 是ObserverWrapper的子类,关于ObserverWrapper这里不做分析,之前的网上分析黏性事件产生原因的文章已经做了介绍。其实就是一个观察者Observer(androidx.lifecycle.Observer)的封装。
当LifecycleBoundObserver 的onStateChanged方法被回调时,如果LiveData的mVersion>observer(其实就是wrapper ObserverWrapper的实例,这里是LifecycleBoundObserver 的实例)的mLastVersion时就会调用其内部observer对象通知观察者。
那么,这个onStateChanged方法是什么时候被调用呢?为什么hook不生效?猜想一下,难道是调用supper.observe(owner,observer);之后,有了观察者,就会立即把之前的数据发送给observer?
我们来验证一下。继续跟进owner.getLifeCycle().addObserver(wrapper);方法,看看这个方法究竟干了啥。进入到了LifeCycle类里面,发现这是一个抽象方法
那么,就去找它的子类。还记得我们在Demo里面,NonStickDemo里面调用注册观察者方法
可以看见,传入了this,因此,我们可以进入AppCompatActivity中去看下getLifeCycle()方法
什么情况,没有?那去父类里面找,继续跟进,进入FragmentActivity里面,还是没有找到,那就继续跟进,ComponentActivity
原来是ComponentActivity实现了这个方法,看下这个方法,返回了mLifecycleRegistry,这个mLifecycleRegistry是LifecycleRegistry的实现类
那么,我们要查看的addObserver(wrapper)方法应该就是在LifecycleRegistry类或者它的父类里面实现的,来看下LifecycleRegistry是啥玩意儿。进去LifecycleRegistry里面看看
看关键地方,先不管这个statefulObserver是啥,也不管dispatchEvent方法里面传入的参数是啥,先进去看看。
哦豁,这样子?原来还真是,在调用owner.getLifecycle().addObserver(wrapper);这个方法添加观察者后,就会立即将之前发送的数据发送给Observer。所以,无论你后面怎么hook,观察者已经接收了数据,更改mLastVersion也没用。
由于发送(就是调用liveData的setValue()或者postValue())事件在注册观察者之前,而且每次setValue都会使liveData的mVersion加1,由于LiveData的mVersion初始值和ObserverWrapper的mLastVersion的初始值都是-1(START_VERSION = -1)所以只要先发送数据,当注册观察者时,livaData的mVersion一定大于ObserverWrapper的初始值且大于其自身的初始值-1。
既然是因为LiveData的mVersion>Observer的mLastVersion造成黏性事件,那么,我们要想实现非粘性事件,可以在注册观察者之前,利用反射,将之前已经调用了setValue或者postValue的LiveData的mVersion设置为-1就可以了。
新建BusMutableLiveData类继承MutableLiveData,并重写其observe方法,然后在LiveDataBus类的getChanel()方法中使用,代码如下:
private class BusMutableLiveDataextends MutableLiveData { @Override public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) { hookVersion(this); super.observe(owner, observer); } } private void hookVersion(BusMutableLiveData data) { Class> liveDataClass = LiveData.class; Field mVersion = null; try { mVersion = liveDataClass.getDeclaredField("mVersion"); mVersion.setAccessible(true); int version = ((int) mVersion.get(data)); Log.e(TAG, "hookVersion:LiveData.mVersion = " + version); if (version != -1) { mVersion.set(data, -1); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
private synchronized BusMutableLiveDatagetChenal(String key) { if (caches.get(key) == null) { caches.put(key, new BusMutableLiveData ()); } return caches.get(key); }
修改后我们再来看下效果
可以看见,没有黏性数据了,也不影响正常数据的接收。
public class Databus{ private static Databus databus; private static String TAG = "DatabusUtil"; private Map caches; private Databus() { caches = new HashMap<>(); } public static Databus getInstance() { if (databus == null) { databus = new Databus(); } return databus; } private synchronized BusMutableLiveData getChenal(String key) { if (caches.get(key) == null) { caches.put(key, new BusMutableLiveData ()); } return caches.get(key); } public void publishSet(String key, T value) { MutableLiveData chenal = getChenal(key); chenal.setValue(value); } public void publishPo(String key, T value) { synchronized (Databus.class) { MutableLiveData chenal = getChenal(key); chenal.postValue(value); } } public void regist(String key, LifecycleOwner lifecycle, Observer observer) { getChenal(key).observe(lifecycle, observer); } private class BusMutableLiveData extends MutableLiveData { @Override public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) { hookVersion(this); super.observe(owner, observer); } } private void hookVersion(BusMutableLiveData data) { Class> liveDataClass = LiveData.class; Field mVersion = null; try { mVersion = liveDataClass.getDeclaredField("mVersion"); mVersion.setAccessible(true); int version = ((int) mVersion.get(data)); Log.e(TAG, "hookVersion:LiveData.mVersion = " + version); if (version != -1) { mVersion.set(data, -1); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
本人是初学者,在使用过程中发现了这个问题,如果有理解不恰当之处,欢迎大家提出宝贵的意见。