EventBus设计模式剖析(三)观察者模式

上一篇 EventBus设计模式剖析(二)建造者模式

EventBus:

由开源组织greenrobot开发的事件发布-订阅总线库。

设计模式:

软件开发中问题的解决套路。

观察者模式简介

定义:定义对象间一种一对的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到广播通知并被自动更新。

其实观察者模式(Observer Pattern)叫做发布-订阅模式更合适。发布者一旦更新消息,所有订阅者都能收到。观察者模式也很适用于UI事件触发和侦听,消息交换等场景
Observer和Observable是JDK中的内置类型,若一个对象继承了Observer类,那么这段代码大概率用了观察者模式。

EventBus类中的观察者模式

EventBus作为事件发布-订阅总线库,必然使用了发布-订阅模式。
继续使用之前文章的代码分析做分析。EventBus类通过register()方法注册成为订阅者(观察者)。

 // 1 注册广播
EventBus.getDefault().register(EventBusActivity.this);

EventBus通过post()方法进行发布,即拿到EventBus.getDefault()的线程自动成为发布者(被观察者)。EventBus以单例模式创建,就会变成长期跟随在这个Android应用的事件收发中心,贯穿全局。

 // 4 发送消息
EventBus.getDefault().post(new MessageEvent("主线程发送过来的数据"));

现在我们来看看如何register(注册)和如何post(发布)的。

private final Map, CopyOnWriteArrayList> subscriptionsByEventType;
private final Map>> typesBySubscriber;
private final SubscriberMethodFinder subscriberMethodFinder;

EventBus(EventBusBuilder builder) {
    //以事件类的class对象为键值,记录注册方法信息,值为一个Subscription的列表
    subscriptionsByEventType = new HashMap, CopyOnWriteArrayList>(); 
    //以注册的类为键值,记录该类所注册的所有事件类型,值为一个Event的class对象的列表
    typesBySubscriber = new HashMap>>();
}

//  注册给定的订阅服务器以接收事件,false表示不是粘性事件。
public void register(Object subscriber) {
    register(subscriber, false, 0);
}

//  注册给定的订阅服务器以接收事件,并指定阅者优先级,从而影响事件交付顺序,false表示不是粘性事件。
public void register(Object subscriber, int priority) {
    register(subscriber, false, priority);
}

// 同步方法,只能单线程访问,直到该线程释放同步锁,下一线程才可以访问
private synchronized void register(Object subscriber, boolean sticky, int priority) {
    List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass()); // 订阅方法集合
    for (SubscriberMethod subscriberMethod : subscriberMethods) {
        subscribe(subscriber, subscriberMethod, sticky, priority); // 订阅函数
    }
}

// 必须在同步块中调用 
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
    Class eventType = subscriberMethod.eventType; // 获取订阅方法的事件类
    CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType); // // 创建订阅类 subscriptions集合,内部子项Subscription
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority); // new一个我们想要添加的 Subscription
    // 获取订阅了此事件类的所有订阅者信息列表,如果不存在则将其加入订阅者信息列表,如果已经存在此订阅者信息则抛出已注册的异常
    if (subscriptions == null) { // subscriptions集合为空
        subscriptions = new CopyOnWriteArrayList();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        if (subscriptions.contains(newSubscription)) { // 若集合中已经有newSubscription,不必注册了,抛出异常
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "+ eventType);
        }
    }

    int size = subscriptions.size(); // subscriptions集合大小
    for (int i = 0; i <= size; i++) { // 遍历,若优先级较高,则插入;若优先级最低(i == size),尾部插入。
        if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
            subscriptions.add(i, newSubscription); 
            break;
        }
    }

    List> subscribedEvents = typesBySubscriber.get(subscriber); // 获取此订阅者实例订阅的所有事件类的列表
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    subscribedEvents.add(eventType); // 将此事件类加入 订阅者事件类列表中
    ......
}

订阅过程是在维护两个Map,一个是subscriptionsByEventType,另外一个是typesBySubscriber。首先来说subscriptionsByEventType:

private final Map, CopyOnWriteArrayList> subscriptionsByEventType;

subscriptionsByEventType内部结构是Map<事件类,该事件的所有订阅者>。

private final Map>> typesBySubscriber;

typesBySubscriber内部结构是Map<订阅者,该订阅者所订阅的所有事件>。
其实这两个对象结构不同,但是所存储的信息是完全一致的。那为什么要重复定义呢?
因为EventBus是一个发布订阅系统,subscriptionsByEventType是从发布者角度订制,而typesBySubscriber是从订阅者角度订制。

基于观察者模式构建的其他代码

1、Android的BroadcastRecevier广播机制
2、ListView中的notifyDataSetChanged()方法

参考文献

1、设计模式|菜鸟教程:https://www.runoob.com/design-pattern/design-pattern-tutorial.html
2、《Android源码设计模式解析与实战》何红辉,关爱民著
3、蕉下孤客:https://www.jianshu.com/p/1b68ace4600a
4、野生的安卓兽:https://www.jianshu.com/nb/10598547

上一篇 EventBus设计模式剖析(二)建造者模式

All is well.

你可能感兴趣的:(EventBus设计模式剖析(三)观察者模式)