美文网首页
消息总线LiveDataBus,替换Rxbus/eventBus

消息总线LiveDataBus,替换Rxbus/eventBus

作者: remax1 | 来源:发表于2020-07-16 11:37 被阅读0次

    前言

    对于Android系统来说,消息传递是最基本的组件,每一个App内的不同页面,不同组件都在进行消息传递。在这之前,我们会用广播或者eventBus或者Rxbus去做消息的传递,但是现在开始我们可以用LiveDataBus了,相比前面这些消息总线框架,LiveDataBus有如下好处:
    1.LiveDataBus可以减小APK包的大小 由于LiveDataBus只依赖Android官方Android Architecture Components组件的LiveData,没有其他依赖,本身实现只有一个类。而Rxbus借助Rxjava,需要引入Rxjava的支持库。

    2.LiveDataBus可以感知activity的生命周期,没有内存泄漏的风险。

    3.谷歌推荐。

    Rxbus

    在这里,还是先比较一下Rxbus

    public class RxBus {
    
        private static volatile RxBus mDefaultInstance;
    
        private RxBus() {
        }
    
        public static RxBus getDefault() {
            if (mDefaultInstance == null) {
                synchronized (RxBus.class) {
                    if (mDefaultInstance == null) {
                        mDefaultInstance = new RxBus();
                    }
                }
            }
            return mDefaultInstance;
        }
    
        private final Subject<Object> _bus = PublishSubject.create().toSerialized();
    
        public void send(Object o) {
            _bus.onNext(o);
        }
    
        public Observable<Object> toObservable() {
            return _bus;
        }
    
        /**
         * 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者
         *
         * @param eventType 事件类型
         * @param <T>
         * @return
         */
        public <T> Observable<T> toObservable(Class<T> eventType) {
            return _bus.ofType(eventType);
        }
    
        /**
         * 提供了一个新的事件,根据code进行分发
         *
         * @param code 事件code
         * @param o
         */
        public void post(int code, Object o) {
            _bus.onNext(new RxBusMessage(code, o));
    
        }
    
        /**
         * 根据传递的code和 eventType 类型返回特定类型(eventType)的 被观察者
         * 对于注册了code为0,class为voidMessage的观察者,那么就接收不到code为0之外的voidMessage。
         *
         * @param code      事件code
         * @param eventType 事件类型
         * @param <T>
         * @return
         */
        public <T> Observable<T> toObservable(final int code, final Class<T> eventType) {
            return _bus.ofType(RxBusMessage.class)
                    .filter(new Predicate<RxBusMessage>() {
                        @Override
                        public boolean test(RxBusMessage rxBusMessage) throws Exception {
                            //过滤code和eventType都相同的事件
                            return rxBusMessage.getCode() == code && eventType.isInstance(rxBusMessage.getObject());
                        }
                    }).map(new Function<RxBusMessage, Object>() {
                        @Override
                        public Object apply(RxBusMessage rxBusMessage) throws Exception {
                            return rxBusMessage.getObject();
                        }
                    }).cast(eventType);
        }
    
        /**
         * 判断是否有订阅者
         */
        public boolean hasObservers() {
            return _bus.hasObservers();
        }
    
    }
    

    在RxJava中有个Subject类,它继承Observable类,同时实现了Observer接口,因此Subject可以同时担当观察者和被观察者的角色,使用PublishSubject来创建一个Subject对象PublishSubject只有被订阅后才会把接收到的事件立刻发送给观察者。

    在需要接收事件的地方,订阅该Subject对象,之后如果Subject对象接收到事件,则会发射给该观察者,此时Subject对象充当被观察者的角色。

    完成了订阅,在需要发送事件的地方将事件发送给之前被订阅的Subject对象,则此时Subject对象作为观察者接收事件,然后会立刻将事件转发给订阅该Subject对象的订阅者,以便观察者处理相应事件,到这里就完成了事件的发送与处理。

    最后就是取消订阅的操作了,RxJava中,订阅操作会返回一个Disposable对象,调用Disposable.dispose()以便在合适的时机取消订阅,防止内存泄漏。

    LiveDataBus

    public class LiveDataBusX {
        //存放订阅者
        private Map<String, BusMutiableLiveData<Object>> bus;
        private static LiveDataBusX liveDataBus = new LiveDataBusX();
    
        private LiveDataBusX() {
            bus = new HashMap();
        }
        public static LiveDataBusX getInstance() {
            return liveDataBus;
        }
        //注册订阅者
        public synchronized <T> BusMutiableLiveData<T> with(String key, Class<T> type) {
            if(!bus.containsKey(key)){
                bus.put(key,new BusMutiableLiveData<Object>());
            }
            return (BusMutiableLiveData<T>)bus.get(key);
        }
    
        public static class BusMutiableLiveData<T> extends MutableLiveData{
            @Override
            public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
                super.observe(owner, observer);
                hook(observer);
            }
    
            private void hook(Observer<? super T> observer) {
                try{
                    //1.得到mLastVersion
                    Class<LiveData> liveDataClass=LiveData.class;
                    Field mObserversFeild=liveDataClass.getDeclaredField("mObservers");
                    mObserversFeild.setAccessible(true);
                    //获取到这个成员变量的对象
                    Object mObserversObject=mObserversFeild.get(this);
                    //得到map对应的class对象
                    Class<?> mObserversClass=mObserversObject.getClass();
                    //需要执行get方法
                    Method get=mObserversClass.getDeclaredMethod("get",Object.class);
                    get.setAccessible(true);
                    Object invokeEntry=get.invoke(mObserversObject,observer);
    
                    Object observerWraper=null;
    
                    if(invokeEntry!=null && invokeEntry instanceof Map.Entry){
                        observerWraper=((Map.Entry)invokeEntry).getValue();
                    }
                    if(observerWraper==null){
                        throw new NullPointerException("observerWraper is null!");
                    }
                    //得到ObserveWraper的类对象 ,编译擦除问题
                    Class<?> superclass=observerWraper.getClass().getSuperclass();
                    Field mLastVersion=superclass.getDeclaredField("mLastVersion");
                    mLastVersion.setAccessible(true);
                    //2.得到mVersion
                   Field mVersion=liveDataClass.getDeclaredField("mVersion");
                   mVersion.setAccessible(true);
                    //3.mLastVersion填到mVersion中
                    Object mVersionValue=mVersion.get(this);
                    mLastVersion.set(observerWraper,mVersionValue);
    
                }catch(Exception e){
                    e.printStackTrace();
                }
    
            }
        }
    
    }
    

    在使用这个LiveDataBus的过程中,订阅者会收到订阅之前发布的消息,这是不可接受的,在LifeData这篇文章中,讲述了原因,思路就是在把observerWraper的mLastVersion设置成个liveData的mVersion一样的值。

    相关文章

      网友评论

          本文标题:消息总线LiveDataBus,替换Rxbus/eventBus

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