美文网首页
基于LiveData的仿EventBus快速实现:LiveDat

基于LiveData的仿EventBus快速实现:LiveDat

作者: 耗子JF | 来源:发表于2019-10-08 15:13 被阅读0次

    对于黏性广播的问题,我们需要在之前的版本中,加上一个可选设置,默认为关闭状态;但是如何关闭这种功能,我们需要从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();
                }
            }
        }
    
    }
    
    Back:基于LiveData的仿EventBus快速实现:LiveDataBus

    相关文章

      网友评论

          本文标题:基于LiveData的仿EventBus快速实现:LiveDat

          本文链接:https://www.haomeiwen.com/subject/myipuctx.html