基于RxJava2和编译时注解的“EventBus”

概述:

目前大多数开发者使用 EventBus 作为事件总线通信库,在RxJava/RxAndroid大火之际,不少人使用RxJava作为事件的调度和线程切换的处理中心实现事件通信库。它们都是使用反射的方式去执行订阅者的方法,总所周知大量使用反射很影响程序的性能和效率,所以我们更青睐使用编译时注解。比如当前流行的第三方库Dagger2, ButterKnife 等,都是通过编译时注解,动态生成Java文件,避免反射带来的损耗,今天给大家介绍的RxEventProcessor就是基于RxJava2和编译时注解的基础实现EventBus的功能

项目地址

配置

  1. 在项目的根build.gradle中添加jitpack地址
    allprojects {
        repositories {
            google()
            jcenter()
            maven { url 'https://jitpack.io' }
        }
    }
复制代码
  1. 在对应module的build.gradle下添加依赖和注解处理器,就可以使用了
dependencies {
    compile 'com.github.TkkSoCool.RxEventProcessor:api:test1.0.1'
    annotationProcessor 'com.github.TkkSoCool.RxEventProcessor:compiler:test1.0.1'
}
复制代码

使用示例

1.注册&取消注册

在activity中的oncreate()方法里初始化RxEventProcessor

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_demo);
    RxEventProcessor.get().bind(this);
}
复制代码

使用RxEventProcessor的时候一定要在适当的时候取消注册,不然导致该对象无法正常被GC回收导致内存泄漏

@Override
protected void onDestroy() {
    super.onDestroy();
    RxEventProcessor.get().unBind(this);
}
复制代码

2.事件的发送

RxEventProcessor可以发送任意类型个数量的对象,相对于EventBus无须再次定义事件类,可以发送没有参数以及多个参数的事件,更加灵活简洁。

  • 发送无参事件
   RxEventProcessor.get().post("tag_no_par");
复制代码
  • 发送多个参数的事件
   RxEventProcessor.get().post("tag_pars",object1,object2...);
复制代码

注意:如果发送的事件的参数与对应方法的参数类型和数量不一致会抛出异常。

3.事件的订阅

RxEventProcessor事件的订阅很简单,使用Recipient注解标注对应的方法,并指定事件的Tag和事件发送处理的线程即可

    /**
    * 接收无参数的事件
    */
   @Recipient(tag = RxEventProcessorTag.NO_PAR,observeOn = ThreadType.MAIN,subscribeOn = ThreadType.NEW)
   public void onSendEventNoPar(){
       textView.append("\n onSendEventNoPar ");
   }

   /**
    * 接收一个参数的事件
    */
   @Recipient(tag = RxEventProcessorTag.ONE_PAR,observeOn = ThreadType.MAIN,subscribeOn = ThreadType.NEW)
   public void onSendEventOnePar(int size){
       textView.append("\n onSendEventOnePar size = " + size);
   }
   /**
    * 接收两个个参数的事件
    */
   @Recipient(tag = RxEventProcessorTag.TWO_PAR,observeOn = ThreadType.MAIN,subscribeOn = ThreadType.NEW)
   public void onSendEventTwoPar(int size,String name){
       textView.append("\n onSendEventTwoPar size = " + size + "  name = " + name);
   }
复制代码

实现流程

1.注解处理器程

在项目的编译阶段,通过解析Recipient注解,生成对应的Java文件,用于事件的注册,实际上就是根据订阅方法的注解信息,给RxJava的事件处理器添加对应的订阅者(观察者),当消息发送执行后,直接调用订阅方法,不需要通过反射,上例中具体生成的代码如下,通过filter操作符匹配订阅方法对应的tag,同时指定了事件发送和执行的线程,最后在onNext方法中执行订阅方法。具体实现可以查看源码的compiler模块.

package com.tkk.eventprocessor;
import com.tkk.api.Binder;
import com.tkk.api.Unbinder;
import com.tkk.api.entity.Event;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Predicate;
import io.reactivex.processors.FlowableProcessor;
import io.reactivex.subscribers.ResourceSubscriber;
import java.lang.Exception;
import java.lang.Override;
import java.lang.Throwable;
public class FragmentObserver_SUBSCRIBE_INFO implements Binder<FragmentObserver>, Unbinder {
   private CompositeDisposable mCompositeDisposable = new CompositeDisposable();
   @Override
   public void bind(final FragmentObserver target, FlowableProcessor<Event> flowable) {
       mCompositeDisposable.add(flowable.subscribeOn(io.reactivex.schedulers.Schedulers.newThread())
               .observeOn(io.reactivex.android.schedulers.AndroidSchedulers.mainThread())
               .filter(new Predicate<Event>() {
                   @Override
                   public boolean test(Event event) throws Exception {
                       return event.getTag().equals("1");
                   }
               })
               .subscribeWith(new ResourceSubscriber<Event>() {
                   @Override
                   public void onNext(Event event) {
                       Object[] objects = event.getData();
                       target.onSendEventNoPar();
                   }
                   @Override
                   public void onError(Throwable t) {
                       t.printStackTrace();
                   }
                   @Override
                   public void onComplete() {
                   }
               })
       );
       mCompositeDisposable.add(flowable.subscribeOn(io.reactivex.schedulers.Schedulers.newThread())
               .observeOn(io.reactivex.android.schedulers.AndroidSchedulers.mainThread())
               .filter(new Predicate<Event>() {
                   @Override
                   public boolean test(Event event) throws Exception {
                       return event.getTag().equals("2");
                   }
               })
               .subscribeWith(new ResourceSubscriber<Event>() {
                   @Override
                   public void onNext(Event event) {
                       Object[] objects = event.getData();
                       target.onSendEventOnePar((Integer) objects[0]);
                   }
                   @Override
                   public void onError(Throwable t) {
                       t.printStackTrace();
                   }
                   @Override
                   public void onComplete() {
                   }
               })
       );
       mCompositeDisposable.add(flowable.subscribeOn(io.reactivex.schedulers.Schedulers.newThread())
               .observeOn(io.reactivex.android.schedulers.AndroidSchedulers.mainThread())
               .filter(new Predicate<Event>() {
                   @Override
                   public boolean test(Event event) throws Exception {
                       return event.getTag().equals("3");
                   }
               })
               .subscribeWith(new ResourceSubscriber<Event>() {
                   @Override
                   public void onNext(Event event) {
                       Object[] objects = event.getData();
                       target.onSendEventTwoPar((Integer) objects[0], (java.lang.String) objects[1]);
                   }
                   @Override
                   public void onError(Throwable t) {
                       t.printStackTrace();
                   }
                   @Override
                   public void onComplete() {
                   }
               }) );
   }
   @Override
   public void unBind() {
       mCompositeDisposable.clear();
   }
}
复制代码

2.订阅方法的注册

RxEventProcessor的bind方法很简单,首先判断当前对象是否已经注册,如果没有注册就通过反射获取到上面处理器生成的Java文件实例,并执行bind的方法,初始化RxJava的订阅者(观察者)信息,并保存Unbinder对象,用于取消绑定。

  public void bind(Object target) {
      int subscriberId = target.hashCode();
      //判断是否已经注册
      if (!subscriberUnbinds.containsKey(subscriberId)) {
          String className = target.getClass().getName();
          try {
              Class<?> finderClass = Class.forName(className + "_SUBSCRIBE_INFO");
              Object targetEventProcessor = finderClass.newInstance();
              Binder binder = (Binder) targetEventProcessor;
              Unbinder unbinder = (Unbinder) targetEventProcessor;
              binder.bind(target, mProcessor);
              subscriberUnbinds.put(subscriberId, unbinder);
          } catch (ClassNotFoundException e) {
              e.printStackTrace();
          } catch (InstantiationException e) {
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              e.printStackTrace();
          }
      }
  }
复制代码

3.事件的处理与发送

RxEventProcessor使用RxJava2中的FlowableProcessor作为事件的发射器,它在订阅观察者后不会立即发送事件,需要手动发送。下面就是事件的发送过程

  /**
   * 发送事件
   * @param tag
   * @param objects 订阅方法参数
   */
  private FlowableProcessor<Event> mProcessor;
  public void post(String tag, Object... objects) {
      Event event = new Event(tag, objects);
      mProcessor.onNext(event);
  }
复制代码

结语

相对于EventBus,虽然RxEventProcessor在订阅方法的参数传递上面更加灵活方便,方法的执行效率更高,但是EventBus更加稳定,功能性也更加丰富,同时也经受了大量的考验,如果你的项目里面没有使用RxJava,那么还是建议使用EventBus。现在RxEventProcessor处理测试阶段,也不建议在正式项目中使用。

最后,感谢大家查看这篇文章,写的不好的或者有问题的,欢迎大家留言交流~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值