基于LiveData的仿EventBus快速实现:LiveDataBus 功能完善

对于黏性广播的问题,我们需要在之前的版本中,加上一个可选设置,默认为关闭状态;但是如何关闭这种功能,我们需要从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, 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() {
                    @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 extends MutableLiveData {

        //该字段预留给LiveDataBus用于有需要黏性广播的用户
        private boolean isWithStick = false;

        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
            super.observe(owner, observer);
            if(!isWithStick){
                hookToCleanStick(observer);
            }
        }

        public void setWithStick(boolean withStick){
            this.isWithStick = withStick;
        }

        //此处代码为hook的重点段,有兴趣的可以对照源码来看
        private void hookToCleanStick(Observer 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> 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 with(String key){
        return with(key, Object.class,false);
    }

    public MyMutableLiveData with(String key, boolean withStick){
        return with(key, Object.class,withStick);
    }

    public  MyMutableLiveData with(String key, Class clz){
        return with(key,clz,false);
    }

    public  MyMutableLiveData with(String key, Class clz, boolean withStick){
        if(!bus.containsKey(key)){
            MyMutableLiveData liveData = new MyMutableLiveData<>();
            bus.put(key,liveData);
        }
        MyMutableLiveData liveData = bus.get(key);
        liveData.setWithStick(withStick);
        return (MyMutableLiveData) liveData;
    }

    public class MyMutableLiveData extends MutableLiveData {

        private boolean isWithStick = false;

        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
            super.observe(owner, observer);
            if(!isWithStick){
                hookToCleanStick(observer);
            }
        }

        public void setWithStick(boolean withStick){
            this.isWithStick = withStick;
        }

        private void hookToCleanStick(Observer 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();
            }
        }
    }

}
 
 
Back:基于LiveData的仿EventBus快速实现:LiveDataBus

你可能感兴趣的:(基于LiveData的仿EventBus快速实现:LiveDataBus 功能完善)