对于黏性广播的问题,我们需要在之前的版本中,加上一个可选设置,默认为关闭状态;但是如何关闭这种功能,我们需要从LiveData事件分发机制里去查看:
//源码查看,包括postValue最终都是调用SetValue接口实现
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;//这里有个一个版本,用于标记值是否发生变化,往后看就能发现其功能
mData = value;
dispatchingValue(null);
}
//接上面的value分发机制
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//最终数据是从这里分发出去的
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
//具体分发过程
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
//具体分发过程
private void considerNotify(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;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);//这里便是我们最终的分发调用点
}
通过以上源码分析,我们可以看出,如果我们需要阻止在我们执行:
LiveDataBus_Ver1.get()
.with("bus1",String.class)
.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String msg) {
LogW.d("LiveDataBus_Ver1"," msg received:"+msg);
}
});
这个过程中,最小影响的原则下,我们只需要在调用.observe()方法的时候,满足observer.mLastVersion >= mVersion这个条件即可完美完成这个目的,而不会担心影响其余的正常事件分发机制,即observer.mLastVersion = mVersion将这段代码在我们调用.observe()执行一次即可,这个时候我们就需要通过hook来完成这个方案的实施,为此我们需要重写MutableLiveData的oberve方法:
public class MyMutableLiveData<T> extends MutableLiveData<T> {
//该字段预留给LiveDataBus用于有需要黏性广播的用户
private boolean isWithStick = false;
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
super.observe(owner, observer);
if(!isWithStick){
hookToCleanStick(observer);
}
}
public void setWithStick(boolean withStick){
this.isWithStick = withStick;
}
//此处代码为hook的重点段,有兴趣的可以对照源码来看
private void hookToCleanStick(Observer<? super T> observer){
try {
//获取LiveData的mObservers(源码中我们所有的观察者都存放在这个Map里面)
Field mObserversField = LiveData.class.getDeclaredField("mObservers");
mObserversField.setAccessible(true);
Object mObservers = mObserversField.get(this);
//获取mObservers中observer对应的MAP.ENTITY
//(通过获取我们注册的当前这个观察者对应的MAP.ENTITY,我们能够拿到上面源码里看到的对应的mVersion)
Method methodGet = mObservers.getClass().getDeclaredMethod("get", Object.class);
methodGet.setAccessible(true);
Map.Entry entry = (Map.Entry) methodGet.invoke(mObservers,observer);//通过Map.Entity的get方法拿到对应的观察者
//获取observer对应的observerWrapper
Object observerWrapper = entry.getValue();
//获取当前LivedData中mVersion的值
Field mVersionField = LiveData.class.getDeclaredField("mVersion");
mVersionField.setAccessible(true);
Object mVersion = mVersionField.get(this);
//更新observerWrapper中mLastVersion值为LiveData的mVersion值
Field mLastVersion = observerWrapper.getClass().getSuperclass().getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
mLastVersion.set(observerWrapper,mVersion);
} catch (Exception e) {
e.printStackTrace();
}
}
}
通过以上的hook代码,我们就完成了上面分析的observer.mLastVersion = mVersion这个操作。一下是完整版的LiveDataBus源码:
public class LiveDataBus {
private final Map<String, MyMutableLiveData<Object>> bus;
private LiveDataBus(){
bus = new HashMap<>();
}
private static class SingletonHolder {
/***单例对象实例*/
static final LiveDataBus INSTANCE = new LiveDataBus();
}
public static LiveDataBus get() {
return LiveDataBus.SingletonHolder.INSTANCE;
}
public MyMutableLiveData<Object> with(String key){
return with(key, Object.class,false);
}
public MyMutableLiveData<Object> with(String key, boolean withStick){
return with(key, Object.class,withStick);
}
public <T> MyMutableLiveData<T> with(String key, Class<T> clz){
return with(key,clz,false);
}
public <T> MyMutableLiveData<T> with(String key, Class<T> clz, boolean withStick){
if(!bus.containsKey(key)){
MyMutableLiveData<Object> liveData = new MyMutableLiveData<>();
bus.put(key,liveData);
}
MyMutableLiveData<Object> liveData = bus.get(key);
liveData.setWithStick(withStick);
return (MyMutableLiveData<T>) liveData;
}
public class MyMutableLiveData<T> extends MutableLiveData<T> {
private boolean isWithStick = false;
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
super.observe(owner, observer);
if(!isWithStick){
hookToCleanStick(observer);
}
}
public void setWithStick(boolean withStick){
this.isWithStick = withStick;
}
private void hookToCleanStick(Observer<? super T> observer){
try {
//获取LiveData的mObservers
Field mObserversField = LiveData.class.getDeclaredField("mObservers");
mObserversField.setAccessible(true);
Object mObservers = mObserversField.get(this);
//获取mObservers中observer对应的MAP.ENTITY
Method methodGet = mObservers.getClass().getDeclaredMethod("get", Object.class);
methodGet.setAccessible(true);
Map.Entry entry = (Map.Entry) methodGet.invoke(mObservers,observer);
//获取observer对应的observerWrapper
Object observerWrapper = entry.getValue();
//获取当前LivedData中mVersion的值
Field mVersionField = LiveData.class.getDeclaredField("mVersion");
mVersionField.setAccessible(true);
Object mVersion = mVersionField.get(this);
//更新observerWrapper中mLastVersion值为LiveData的mVersion值
Field mLastVersion = observerWrapper.getClass().getSuperclass().getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
mLastVersion.set(observerWrapper,mVersion);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
网友评论