博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RxBus-实现EventBus之post
阅读量:5914 次
发布时间:2019-06-19

本文共 7849 字,大约阅读时间需要 26 分钟。

背景

是否有这样的纠结:

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

  • 已经使用rxjava和rxAndroid到你的项目中,但是项目中又同时存在eventbus;因为rx完全可以替换掉eventbus所以导致了过多引入第三方jar包的问题,对于有代码洁癖和瘦身需求的同学们来说简直是一个噩耗;

    如何在最大基础上修改我们已经存在的代码呢,那就是改造一个自己的rxbus,让他使用起来和eventbus一模一样,这样我们只需要将eventbus改名成rxbus即可,其他代码都不需要修改!

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

效果

这里写图片描述

工程目录

这里写图片描述

代码使用

  • 注册-注销-接受事件

    /*接受事件*/ @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的同学一眼就应该能看出,用法完全一模一样

封装原理

封装注解

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

暂时咱们先了解ThreadMode 参数,code参数的使用在结尾再给大家解释(比eventbus添加的一个功能)

ThreadMode 指定接受消息的处理所在的线程,我们这里定义了四种情况

处理模式

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封装

初始化单利对象

感兴趣的同学可以查看另一篇关于单利博客

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
> subscriptionsByEventType = new HashMap<>(); private Map
> eventTypesBySubscriber = new HashMap<>(); private Map
> 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
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() {                    @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
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,可自行替换你使用的版本


源码


建议

转载地址:http://mdwvx.baihongyu.com/

你可能感兴趣的文章
大学毕业三个月,你做了些什么?
查看>>
AS3的反编译
查看>>
【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇一:WPF常用知识以及本项目设计总结...
查看>>
socket shutdown 与 close 函数 的区别
查看>>
Unit Test相关问题汇总
查看>>
基本的sqlplus命令
查看>>
APUE16章的运行示例16-14
查看>>
schema for clojure
查看>>
Android控件(一)下拉刷新:SwipeRefreshLayout
查看>>
SSL/TLS协议运行机制的概述
查看>>
Educational Codeforces Round 10 B. z-sort 构造
查看>>
成都Uber优步司机奖励政策(4月1日)
查看>>
ViewPagerindicator 源码解析
查看>>
Linux 文件基本属性
查看>>
穷养富养知乎见解
查看>>
Shell script for logging cpu and memory usage of a Linux process
查看>>
maven pom文件详解
查看>>
WebView输入框提示
查看>>
初始Dubbo
查看>>
CWebBrowser2获取html的内容
查看>>