通过上篇:LiveData的源码分析 我们知道LiveData的最后一次数据会产生粘性
根本原因就是ObserverWrapper.mLastVersion >= mVersion 没有拦住
所以只要我们想办法在观察者注册的时候(执行observe方法)修改mLastVersion的值让他等于LiveData中维护的mVersion这样这个判断就能拦住,数据也就没有粘性了
如何修改ObserverWrapper实现类LifecycleBoundObserver中的mLastVersion呢?
显然得用反射:
我们先获取LiveData中存储LifecycleBoundObserver的Map--->mObservers的实例,然后再通过get(key)方法获取LifecycleBoundObserver的实例,获取LiveData中mVersion的值,最后修改LifecycleBoundObserver的实例的mLastVersion的值让他等于mVersion就大功告成了
代码:
这是我直接改造的LiveData的代码:
public class MyLiveData<T> extends MutableLiveData<T>{
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
super.observe(owner, observer);
hook(observer);
}
private void hook(Observer<? super T> observer) {
try {
//解决粘性的关键就是mLastVersion = mVersion
Class<?> liveDataClass = LiveData.class;
//先找到保存LifecycleBoundObserver的map
Field mObserversField = liveDataClass.getDeclaredField("mObservers");
mObserversField.setAccessible(true);
//Field.get(Field所在的类的实例)方法获取map的实例 反射基础
Object mObserversObj = mObserversField.get(MyLiveData.this);
Class<?> mObserversClass = mObserversObj.getClass();
//获取get方法信息
Method mapMethodGet = mObserversClass.getDeclaredMethod("get",Object.class);
mapMethodGet.setAccessible(true);
//mObservers就是以 observer为key以 Map.Entry<Observer<? super T>, ObserverWrapper>为value的
//通过mObserver.get(observer)获取Map.Entry<Observer<? super T>, ObserverWrapper>的实例
Object obj = mapMethodGet.invoke(mObserversObj,observer);
//获取Entry的class
Class<?> observerWrapperClass = obj.getClass();
//获取Entry的getValue方法的信息
Method getValue = observerWrapperClass.getDeclaredMethod("getValue");
getValue.setAccessible(true);
//执行Entry实例的getValue方法获取LifecycleBoundObserver实例
Object wrapper = getValue.invoke(obj);
Class<?> lifecycleBoundObserverClass = wrapper.getClass();
//因为mLastVersion在父类中,子类的class不包含父类的信息 泛型基础,所以需要得到父类的class信息
Class<?> wrapperClass = lifecycleBoundObserverClass.getSuperclass();
Field mLastVersionField = wrapperClass.getDeclaredField("mLastVersion");
mLastVersionField.setAccessible(true);
//下面是取LiveData中维护的mVersion的值
Field mVersionField = liveDataClass.getDeclaredField("mVersion");
mVersionField.setAccessible(true);
int mVersion = mVersionField.getInt(MyLiveData.this);
//修改mLastVersion中的值
mLastVersionField.set(wrapper,mVersion);
} catch (Exception e) {
e.printStackTrace();
}
}
}