Android消息传递之基于RxJava实现一个EventBus - RxBus

前言:

    上篇文章学习了Android事件总线管理开源框架EventBus,EventBus的出现大大降低了开发成本以及开发难度,今天我们就利用目前大红大紫的RxJava来实现一下类似EventBus事件总线管理,现在很多人都在说用这种方式来替代EventBus,今天我们从开发效率,开发难度等维度来分析一下到底能不能取代EventBus? 先回顾一下什么是EventBus?请看这篇文章Android消息传递之EventBus 3.0使用详解(三)

    消息传递相关文章地址:

 需求:

      虽然软件工程师就害怕听见“需求”这两个字,但是一切功能来源于需求,我们要基于RxJava实现一个publish/subscribe消息总线管理模型,这里假设你已经知道如何使用RxJava了。下面看看如何实现。

RxBus实现过程:

 1.)build.gradle中添加RxJava、RxAndroid引用
  compile 'io.reactivex:rxandroid:1.1.0'
  compile 'io.reactivex:rxjava:1.1.2'
2.)声明一个管理事件总线的单例
public class RxBus {
    private ConcurrentHashMap<Object, List<Subject>> subjectMapper = new ConcurrentHashMap<>();
    private static volatile RxBus instance;

    private RxBus() {
    }

    public static RxBus getInstance() {
        RxBus inst = instance;
        if (inst == null) {
            synchronized (RxBus.class) {
                inst = instance;
                if (inst == null) {
                    inst = new RxBus();
                    instance = inst;
                }
            }
        }
        return inst;
    }
}

考虑到RxBus单例很有可能多线程并发访问,这种存储事件总线采用ConcurrentHashMap

3.)订阅者实现注册/解除注册方法

注册/解注册都以一个tag为唯一标示,这里采用的是事件的Class为tag,来实现一个Event事件对象可以对应多个订阅者。

  /**
     * 注册
     *
     * @param tag
     * @return
     */
    public <T> Observable<T> register(@NonNull Class<T> tag) {
        List<Subject> subjectList = subjectMapper.get(tag);
        if (null == subjectList) {
            subjectList = new ArrayList<>();
            subjectMapper.put(tag, subjectList);
        }
        Subject<T, T> subject = PublishSubject.create();
        subjectList.add(subject);
        return subject;
    }

    /**
     * 解除注册
     *
     * @param tag
     */
    public <T> void unregister(@NonNull Class<T> tag, @NonNull Observable observable) {
        List<Subject> subjects = subjectMapper.get(tag);
        if (null != subjects) {
            subjects.remove(observable);
            if (subjects.isEmpty()) {
                subjectMapper.remove(tag);
            }
        }
    }
4.)实现发送消息、清除所有注册

发送一个事件消息是通过获取当前事件下的订阅者列表,然后通过一个循环进行事件传递。至于事件运行在哪个线程中由订阅者决定。

 /**
     * 发送消息
     *
     * @param event
     */
    public <T> void post(@NonNull Object event) {
        List<Subject> subjectList = subjectMapper.get(event.getClass());
        if (subjectList != null && !subjectList.isEmpty()) {
            for (Subject subject : subjectList) {
                subject.onNext(event);
            }
        }
    }

    /**
     * 清除订阅
     */
    public void clear() {
        if (subjectMapper.isEmpty()) {
            return;
        }
        subjectMapper.clear();
    }
5.)如何使用

事件的订阅者的注册和清除所有注册,订阅者没订阅一个类型的事件都要返回一个Observable对象,这也是个人觉得比较头疼的一件事,很难实现一个订阅者对应多个事件类型,而且解注册的时候也需要这些Observable对象进行一一解除。

    private Observable<DataSynEvent> observable;
    private void registerObservable() {
        observable = RxBus.getInstance().register(DataSynEvent.class);
        observable.observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<DataSynEvent>() {
            @Override
            public void call(DataSynEvent event) {
                Log.e(TAG, "event--2-->" + event.getCount());
            }
        });
    }

    private void unRegisterObservable() {
        if (observable != null) {
            RxBus.getInstance().unregister(DataSynEvent.class, observable);
        }
    }

事件的发送者发送事件,发送事件的处理还算比较友好,和EventBus很类似。

  RxBus.getInstance().post(new DataSynEvent());

RxBus、EventBus 对比:

1.从引入依赖包对比

  RxBus 需要引入两个包,EventBus需要引入一个,如果项目中没有使用到RxJava编程的话,并不能减少包的依赖。

2 .从开发难度上对比

  上面也提到了实现RxBus是基于RxJava的,作为一个新的编程方式函数式编程,对开发者的要求多多少少提高了那么一点,而且每一个订阅都需要返回一个Observable,由订阅者写具体的代码 需要执行在哪个线程中,而EventBus 最新版本采用注解预编译的方式,订阅者注册解注册只需调用一个函数,而且通过注解的方式可以标明事件的优先级,接收事件运行在哪个线程,并且能够实现粘性事件,这些RxBus都需要进行二次开发。

3.)从开发效率上对比

   RxBus 需要进行大量的二次开发,否则只能实现简单的事件传递,而EventBus只需简单了解一下API就能上手。如果一个订阅者需要注册多个事件的时候,需要多个Observable全局变量,这不是疯掉了吗,而EventBus已经实现了一个订阅者订阅多个事件,和一个事件对应多个订阅者。

4.)从功能完善上对比

    上面三个对比也说明了,EventBus实现了事件的优先级,订阅事件运行的线程场景,以及粘性事件,这些在RxBus上面都需要进行二次实现。

总结:

    基于RxJava实现简单的事件总线管理是可以的,但是个人觉得想要取代EventBus难免有点说过头了。所以如果项目中没有使用RxJava的话 还是采用EventBus比较靠谱。

 

转载于:https://www.cnblogs.com/whoislcj/p/5816992.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会为您编写一个基于 TypeScript 的类型安全的 EventBus。 首先,我们需要定义一个监听器的类型,每个监听器都需要知道事件的名称和处理事件时接收的参数类型: ```typescript interface Listener<E extends keyof Events> { event: E; handler: (args: Events[E]) => void; } ``` 这里的 `Events` 是我们定义的事件类型。 接下来,我们需要定义一个 `EventBus` 类,这个类将负责监听事件、触发事件以及添加和删除监听器: ```typescript class EventBus<Events extends Record<string, any>> { private listeners: Record<string, Array<Listener<keyof Events>>> = {}; public on<E extends keyof Events>(event: E, handler: Listener<E>['handler']) { if (!this.listeners[event]) { this.listeners[event] = []; } this.listeners[event].push({ event, handler } as Listener<any>); } public off<E extends keyof Events>(event: E, handler: Listener<E>['handler']) { const listeners = this.listeners[event]; if (listeners) { this.listeners[event] = listeners.filter(l => l.handler !== handler); } } public emit<E extends keyof Events>(event: E, args: Events[E]) { const listeners = this.listeners[event]; if (listeners) { listeners.forEach(l => l.handler(args)); } } } ``` 这个 `EventBus` 类的泛型参数 `Events` 表示所有可能触发的事件,其实就是一个对象类型的集合。在 `on` 方法中,我们创建了一个新的监听器并将其添加到对应事件的监听器列表中,如果该事件的监听器列表尚不存在,则会将该列表初始化为空数组;在 `off` 方法中,我们删除一个具体事件的监听器;在 `emit` 方法中,我们触发一个具体事件,并将参数传递给所有监听器。 现在,假设我们有一个 `User` 类和一个 `update` 事件,我们可以这样使用 EventBus: ```typescript interface Events { update: { id: number; name: string }; } class User { public name: string; public eventbus = new EventBus<Events>(); constructor(name: string) { this.name = name; } public updateName(newName: string) { this.name = newName; const id = Math.floor(Math.random() * 100); this.eventbus.emit('update', { id, name: this.name }); } } const user = new User('Alice'); user.eventbus.on('update', ({ id, name }) => { console.log(`User ${id} has been updated to "${name}"`); }); user.updateName('Bob'); ``` 在这个例子中,我们定义了一个 `User` 类,其具有一个 `updateName` 方法,用于更新用户名,并在修改完成后触发 `update` 事件。我们在 `User` 类中创建了一个 `eventbus` 属性,它是 `EventBus` 的实例,并将 `Events` 对象作为泛型参数传递给它。我们使用 `on` 方法来监听 `update` 事件,使用 `emit` 方法在更新完成后触发该事件。 在 `on` 方法中,我们传递一个函数参数,它接收一个 `update` 事件的参数。因为我们已经使用泛型约束了 `EventBus` 类的类型,所以事件的名称和参数类型都是类型安全的。 希望这个示例对你有所帮助,如果你有问题,请随时向我提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值