0%

级联更新-基于EventBus发布订阅的应用

前段时间,小名同学review原有系统时,提出我们的系统应该引入用于级联更新的机制。说白了,就是发布订阅模式的应用。当时技术评估结论是暂时不需要,但是如果需要实现应该怎么实现呢?后来,我在阅读代码&文档时,发现一个很好的模型可以用来实现上述逻辑。

先说说应用场景。

在写应用系统时,经常会有这样的场景:

  1. 更新订单时,需要将这样的变更通知到供应商&商家&卖家。
  2. 子类目发生变动时,让父类目感知,或者是父父类目感知。
  3. 某一事件触发发送不同类型的通知邮件。
  4. 规则变更产生的一系列级联的操作。

槽糕的实现

如果说只是通知,采用同步&异步调用的方式,也可以满足上述功能。

弊端

  1. 完全面向过程的思考方式,这样的写法会产生又长又软的面条式代码。
  2. 扩展性较差,调用的方式容易将代码写乱,同一类操作格式不统一(毕竟是多人并行开发)。而且如果是异步的话,在主流程里各自需要有起线程的代码。
  3. 耦合性强,“通知”这种类消息的做法,其步骤往往不应该在主流程主要步骤里。
  4. 可读性较差。

有没有什么可以避免上述弊端的解决方案呢?

答案肯定是有的。

首先映入我脑海的就是设计模式中的发布-订阅模式,但是这样需要实现一整套代码逻辑,定义一堆类。虽然能实现,但是方便吗?no。

searching… let me see

EventBus -> https://github.com/greenrobot/EventBus

EventBus is a publish/subscribe event bus for Android and Java.

简单、高效、体积小。
另外,事件总线EventBus的实现,从DDD的角度来说,以事件的弱引用方式对我们的模块和领域边界有很好的解耦作用。**

科普:

Publisher发布者:用于分发我们的Event事件,在EventBus中通过post方法进行分发传送。
Subscriber订阅者:用于接受我们的事件,我们在订阅事件中处理我们接收的数据。
Event事件:任何一个对象都可以作为事件,比如任何字符串,事件是发布者和订阅者之间的通信载体。
EventBus:类似于中转站,将我们的事件进行对应的分发处理。

按照我的理解,示意图如下:
image.png

具体代码的简单实现

EventBus in 3 steps( copied from github)

1.Define events:

1
public static class MessageEvent { /* Additional fields if needed */ }

2.Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:

1
2
@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {/* Do something */};

Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:

1
2
3
4
5
6
7
8
9
10
11
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}

@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}

3.Post events:

1
EventBus.getDefault().post(new MessageEvent())

具体进一步如何实现,可以参考官网:

http://greenrobot.org/eventbus/documentation/how-to-get-started/

from my point:

step1. 定义Event基础类(implements Serializable),在Event中定义EventBus。同时,定义成异步的事件总线 和 异常处理。

1
2
3
4
public static final EventBus TEST_BUS = new AsyncEventBus(
new ThreadPoolExecutor(1,20,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(),new NamedThreadFactory("test")),
((t, context)->{})
);

step2. 定义用于传输的ConcreteEvent类。该类extends Event。有自己的属性信息。

step3. 定义订阅类

  1. 在订阅类初始化的时候,Event.TEST_BUS.register(this);

  2. 在订阅类的方法上配置 @Subscribe

  3. 同时,配置@AllowConcurrentEvents,用于线程安全。

    1
    2
    3
    4
    5
    @Subscribe
    @AllowConcurrentEvents
    public void testSubscribe(@NonNull ConcreteEvent event){
    // TODO 订阅方处理自己的逻辑
    }

参考&致谢

  • https://github.com/greenrobot/EventBus
  • https://www.jianshu.com/p/f9ae5691e1bb
  • https://www.jianshu.com/p/c35f0c545fc9
觉得不错?