RxBus-实现EventBus之post

背景

是否有这样的纠结:java

  • 在已经习惯了EventBus的用法后,转战RxBus使用方法的不一致,致使多余的学习和使用成本react

  • 已经使用rxjava和rxAndroid到你的项目中,可是项目中又同时存在eventbus;由于rx彻底能够替换掉eventbus因此致使了过多引入第三方jar包的问题,对于有代码洁癖和瘦身需求的同窗们来讲简直是一个噩耗;
    如何在最大基础上修改咱们已经存在的代码呢,那就是改造一个本身的rxbus,让他使用起来和eventbus如出一辙,这样咱们只须要将eventbus更名成rxbus便可,其余代码都不须要修改!android

废话到此为止,开始咱们的优化之路git

效果

这里写图片描述

工程目录

这里写图片描述

代码使用

  • 注册-注销-接受事件github

    /*接受事件*/
     @Subscribe(threadMode= ThreadMode.MAIN)
     public void event(EventChangeText changeText){
         tvChange.setText(changeText.getChangeText());
     }
    
     @Override
     protected void onStart() {
         super.onStart();
         /*註冊*/
         RxBus.getDefault().register(this);
     }
    
     @Override
     protected void onDestroy() {
         super.onDestroy();
         /*註銷*/
         RxBus.getDefault().unRegister(this);
     }复制代码
  • 发送消息
    @Override
      public void onClick(View v) {
          switch (v.getId()){
              case  R.id.btn_change_text:
                  RxBus.getDefault().post(new EventChangeText("我修改了-Main"));
                  break;
          }
      }复制代码

用过EventBus的同窗一眼就应该能看出,用法彻底如出一辙ide

封装原理

封装注解

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
    int code() default -1;
    ThreadMode threadMode() default ThreadMode.CURRENT_THREAD;
}复制代码

暂时我们先了解ThreadMode 参数,code参数的使用在结尾再给你们解释(比eventbus添加的一个功能)
ThreadMode 指定接受消息的处理所在的线程,咱们这里定义了四种状况post

处理模式

public enum ThreadMode {

    /** * current thread */
    CURRENT_THREAD,

    /** * android main thread */
    MAIN,


    /** * new thread */
    NEW_THREAD,

    /** * io */
    IO

}复制代码

彻底是rx中自带的四种处理模式学习

处理信息类

封装处理过程当中的相关信息,模式,接收消息对象,code,接受消息类型优化

public class SubscriberMethod {
    public Method method;
    public ThreadMode threadMode;
    public Class<?> eventType;
    public Object subscriber;
    public int code;

    public SubscriberMethod(Object subscriber, Method method, Class<?> eventType, int code,ThreadMode threadMode) {
        this.method = method;
        this.threadMode = threadMode;
        this.eventType = eventType;
        this.subscriber = subscriber;
        this.code = code;
    }


    /** * 调用方法 * @param o 参数 */
    public void invoke(Object o){
        try {
            method.invoke(subscriber, o);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

}复制代码

RxBus封装

集合上面的类,开始咱们的rxbus封装this

初始化单利对象

感兴趣的同窗能够查看另外一篇关于单利博客Android-主Activity不同的单利模式

private static volatile RxBus defaultInstance;
    public static RxBus getDefault() {
        RxBus rxBus = defaultInstance;
        if (defaultInstance == null) {
            synchronized (RxBus.class) {
                rxBus = defaultInstance;
                if (defaultInstance == null) {
                    rxBus = new RxBus();
                    defaultInstance = rxBus;
                }
            }
        }
        return rxBus;
    }复制代码

初始化变量集合

记录注册信息和发布消息信息以及自定义的方法集合

private Map<Class, List<Subscription>> subscriptionsByEventType = new HashMap<>();


    private Map<Object, List<Class>> eventTypesBySubscriber = new HashMap<>();


    private Map<Class, List<SubscriberMethod>> subscriberMethodByEventType = new HashMap<>();复制代码

注册监听

register的时候获取@Subscribe注解的方法的相关信息保存到map,post事件触发的时候调用@Subscribe注解的方法并传入参数.

/** * 注册 * * @param subscriber 订阅者 */
    public void register(Object subscriber) {
        Class<?> subClass = subscriber.getClass();
        Method[] methods = subClass.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Subscribe.class)) {
                //得到参数类型
                Class[] parameterType = method.getParameterTypes();
                //参数不为空 且参数个数为1
                if (parameterType != null && parameterType.length == 1) {

                    Class eventType = parameterType[0];

                    addEventTypeToMap(subscriber, eventType);
                    Subscribe sub = method.getAnnotation(Subscribe.class);
                    int code = sub.code();
                    ThreadMode threadMode = sub.threadMode();

                    SubscriberMethod subscriberMethod = new SubscriberMethod(subscriber, method, eventType, code, threadMode);
                    addSubscriberToMap(eventType, subscriberMethod);

                    addSubscriber(subscriberMethod);
                }
            }
        }
    }复制代码

注销监听

unRegister的移除保存的subscriber、subscriberMethod已经Subscription取消订阅事件
必定要及时的销毁,否则内存泄露

/** * 取消注册 * * @param subscriber */
    public void unRegister(Object subscriber) {
        List<Class> subscribedTypes = eventTypesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unSubscribeByEventType(eventType);
                unSubscribeMethodByEventType(subscriber, eventType);
            }
            eventTypesBySubscriber.remove(subscriber);
        }
    }复制代码

post请求

触发请求

/** * 提供了一个新的事件,单一类型 * * @param o 事件数据 */
    public void post(Object o) {
        bus.onNext(o);
    }复制代码

调用rx处理回调

/** * 用RxJava添加订阅者 * * @param subscriberMethod */
    public void addSubscriber(final SubscriberMethod subscriberMethod) {
        Observable observable;
        if (subscriberMethod.code == -1) {
            observable = toObservable(subscriberMethod.eventType);
        } else {
            observable = toObservable(subscriberMethod.code, subscriberMethod.eventType);
        }

        Subscription subscription = postToObservable(observable, subscriberMethod)
                .subscribe(new Action1<Object>() {
                    @Override
                    public void call(Object o) {
                        callEvent(subscriberMethod.code, o);
                    }
                });
        addSubscriptionToMap(subscriberMethod.eventType, subscription);
    }复制代码

code-post请求,更加方便

在借鉴eventbus消息处理的模式上,新加入code判断方式,这样能够更加快速的添加sub对象,不用一个消息初始化一个类,并且能够同时区分一个消息的不一样处理方式

效果

这里写图片描述

发送消息

public void onClick(View v) {
        switch (v.getId()){
            case  R.id.btn_change_text:
                RxBus.getDefault().post(new EventChangeText("我修改了-Main"));
                break;
            case  R.id.btn_code_simple:
                RxBus.getDefault().post(0x1,"简单的code消息");
                break;
            case  R.id.btn_code_diffrent:
                RxBus.getDefault().post(0x1,new EventChangeText("code方式-我修改了-Main"));
                break;

        }
    }复制代码

接收消息

/*单一code接受处理*/
    @Subscribe(code = 0x1,threadMode= ThreadMode.MAIN)
    public void event(String changeText){
        tvChange.setText(changeText);
    }


    /*code 不一样事件接受處理*/
    @Subscribe(code = 0x1,threadMode= ThreadMode.MAIN)
    public void eventCode(EventChangeText changeText){
        tvChange.setText(changeText.getChangeText());
    }


    /*常規接受事件*/
    @Subscribe(threadMode= ThreadMode.MAIN)
    public void event(EventChangeText changeText){
        tvChange.setText(changeText.getChangeText());
    }复制代码

看完之后估计你们都明白了使用方法,code实现的过车和ThreadMode实现原理同样,在分发事件处理的时候,经过code的判断达到这样的目的结果

/** * 回调到订阅者的方法中 * * @param code code * @param object obj */
    private void callEvent(int code, Object object) {
        Class eventClass = object.getClass();
        List<SubscriberMethod> methods = subscriberMethodByEventType.get(eventClass);
        if (methods != null && methods.size() > 0) {
            for (SubscriberMethod subscriberMethod : methods) {

                Subscribe sub = subscriberMethod.method.getAnnotation(Subscribe.class);
                int c = sub.code();
                if (c == code) {
                    subscriberMethod.invoke(object);
                }

            }
        }
    }复制代码

导入

compile 'com.wzgiceman:RxBus:1.0.2'复制代码

推荐手动导入到本身的工程中,避免多余的第三方jar包导入,只要你的工程中有对rx的支出,将文件copy到工程下面便可:

这里写图片描述

rx资源地址

/*rx-android-java*/
    compile 'io.reactivex:rxjava:+'
    compile 'com.squareup.retrofit:adapter-rxjava:+'
    compile 'com.trello:rxlifecycle:+'
    compile 'com.trello:rxlifecycle-components:+'复制代码

演示工程中使用的是rx2,可自行替换你使用的版本


源码

GitHub源码下载地址-传送门


建议

若是你有任何的问题和建议欢迎加入QQ群告诉我!

相关文章
相关标签/搜索