在两个activity中分别对同一个集合做订阅操作,当一个界面发送消息时,另一个面页面打开时会有吐司,真正的方式是,在一个页面发布消息,才会有吐司产生;那么现在的问题是在跳转到第二个页面刚订阅没有点击吐司就出来了,是因为什么原因导致的呢?上代码
我们跟据上篇文章,来分析,通过with()获取到一个liveData(),如果key相同,获取到的就是同一个liveData;那么observe()方法中,会将当前activity和obersve放到一个边界类中,并把边界类放入到一个集合中()
上面的操作是关于订阅,以及观察者监听livedata数据变化的一个操作,那么什么时候出现了数值的变化,就在于livedata.postValue()做赋值操作,postvalue()->setvalue()->
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
mVersion属性是属于liveData(),在每次进行setValue(),mVersion都会++,通过dispatchingValue()
最终找到了considerNotify()里onChanged()的调用,看下里面的判断结果,如果observer的mLastVersion >=liveData的mVersion,那么结束操作,如果小于onChanged就会被调用,
实际操作就是在订阅的时候,每个页面都有一个observer监听,每个监听都有个属性mLastVersion,mLastVersion的初始值是-1,但是这几个页面只针对一个liveData的存储数据做操作,在第一次postValue时候,livedata的mversion已变成0,而在for()循环遍历边界集合时,第二个observer的mLastVersion是-1,所以代码执行到
if不符合条件就会触发onChanged方法,所以第二个界面刚订阅完,就弹出了吐司
解决方式,就是在第一次订阅初始化的时候,把livedata的mVersion值赋值给observer的mLastVersion方法,这样就能解决,单页面订阅-发布 不影响其他页面
public static class BusMutableLiveDataextends MutableLiveData{
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
super.observe(owner, observer);
hook(observer);
}
private void hook(Observer observer) {
try{
//1.得到mLastVersion
Class liveDataClass=LiveData.class;
Field mObserversField = liveDataClass.getDeclaredField("mObservers");
mObserversField.setAccessible(true);
//获取到这个成员变量对应的对象
Object mObserversObject = mObserversField.get(this);
//得到map
Class mObserversObjectClass = mObserversObject.getClass();
//获取到mObservers对象的get方法
Method get=mObserversObjectClass.getDeclaredMethod("get",Object.class);
get.setAccessible(true);
//执行get方法
Object invokeEntry=get.invoke(mObserversObject,observer);
//取到map中的value
Object observerWraper=null;
if(invokeEntry!=null && invokeEntryinstanceof Map.Entry){
observerWraper=((Map.Entry)invokeEntry).getValue();
}
if(observerWraper==null){
throw new NullPointerException("observerWraper is null");
}
//得到ObserverWrapper的类对象
Class superclass=observerWraper.getClass().getSuperclass();
Field mLastVersion = superclass.getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
//2.得到mVersion
Field mVersion = liveDataClass.getDeclaredField("mVersion");
mVersion.setAccessible(true);
//3.把mVersion的值填入到mLastVersion中
Object mVersionValue=mVersion.get(this);
mLastVersion.set(observerWraper,mVersionValue);
}catch(Exception e){
e.printStackTrace();
}
}
}
网友评论