消息总线LiveDataBus,替换Rxbus/eventBus

前言

对于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 _bus = PublishSubject.create().toSerialized();

    public void send(Object o) {
        _bus.onNext(o);
    }

    public Observable toObservable() {
        return _bus;
    }

    /**
     * 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者
     *
     * @param eventType 事件类型
     * @param 
     * @return
     */
    public  Observable toObservable(Class 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 
     * @return
     */
    public  Observable toObservable(final int code, final Class eventType) {
        return _bus.ofType(RxBusMessage.class)
                .filter(new Predicate() {
                    @Override
                    public boolean test(RxBusMessage rxBusMessage) throws Exception {
                        //过滤code和eventType都相同的事件
                        return rxBusMessage.getCode() == code && eventType.isInstance(rxBusMessage.getObject());
                    }
                }).map(new Function() {
                    @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> bus;
    private static LiveDataBusX liveDataBus = new LiveDataBusX();

    private LiveDataBusX() {
        bus = new HashMap();
    }
    public static LiveDataBusX getInstance() {
        return liveDataBus;
    }
    //注册订阅者
    public synchronized  BusMutiableLiveData with(String key, Class type) {
        if(!bus.containsKey(key)){
            bus.put(key,new BusMutiableLiveData());
        }
        return (BusMutiableLiveData)bus.get(key);
    }

    public static class BusMutiableLiveData extends MutableLiveData{
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
            super.observe(owner, observer);
            hook(observer);
        }

        private void hook(Observer observer) {
            try{
                //1.得到mLastVersion
                Class 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)