otto是square公司出的一个事件库(pub/sub模式),用来简化应用程序之间的通讯。
框架中有两个注解(@Produce、@Subscribe),分别代表生产者,订阅者。在发布事件时,框架会通过识别方法是否含有@Subscribe以及参数来确定相应的方法,然后通过反射执行所有符合该事件的方法。
Bus有5个构造函数,但最宗都会实现Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder)构造方法,其中:
enforcer为Bus指定所在线程,可通过ThreadEnforcer.ANT或者ThreadEnforcer.MAIN来指定,默认为在主线程执行。
identifier相当与给Bus起一个名字,会在toString方法中使用。
handlerFinder是整个event bus的核心,不需要用户来指定,它用于在register、unregister的时候查找所有的Produce、Subscribe。默认的参数为HandlerFinder.ANNOTATED,也就是说HanlderFinder的具体实现类为AnnotatedHandlerFinder。
Bus使用时一般采用单例模式。
如果一个类对某些事件感兴趣,则需要调用register方法来注册监听。
register会首先调用handlerFinder.findAllProducers(object)来找到所有使用了@Produce注解的方法。findAllProducers其实是委托AnnotatedHandlerFinder.findAllProducers方法。
在调用完findAllProducers方法之后,会遍历传入的监听类的Produce方法,并且根据Produce方法的返回类型,来检查是否有对应的Subscribe存在,如果有的话,就会调用Subscribe方法,并将Producer的返回值传入。
Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
for (Class<?> type : foundProducers.ketSet() ) {
final EventProducer producer = foundProducers.get(type);
EventProducer previousProducer = producersByType.putIfAbsent(type, producer);
...
Set<EventHandler> handlers = handlersByType.get(type);
if (handlers != null && !handlers.isEmpty()) {
for (EventHandler handler : handlers) {
dispatchProducerResultToHandler(handler, producer);
}
}
}
这里需要注意的是,Bus对象两个Map类型的常量,用来缓存所有的Producer和Subscriber。
找到了所有的Producers之后,就是调用handlerFinder.findAllSubcribers(object)来寻找object中使用@Subscriber注解的方法,过程和findAllProducers类似,唯一不同的是一个事件中可以有多个Subscribe,却只能有一个Producer,根据他们的返回值类型可以判断。
找到监听类所有的subscribe方法自后,就需要查看Bus中有和这些subscribe对应的producer方法,如果有的话,就会立即调用subscribe方法。这也就是文档上说的,一但有新的subscribe订阅了某一事件,并且该事件有对应的producer,那么subscribe方法就会立即被调用,并且传入producer方法的返回值。
post(Object event)方法用来发送事件给所有的订阅者。它接受的是一个Object类型,说明otto的事件可以是任意类型的对讲。
Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());
for (Class<?> eventType :disPatchTypes) {
...
}
post方法首先会获取所有event对象的父类,饭后遍历这些父类,找到他们所有的订阅者,发送事件,这表明任何订阅了event对象的订阅者也都会收到event事件。
值得注意的是Otto使用ThreadLocal类型来存放事件队列,这样极大的简化了多线程模式下的开发。
unregister方法做的事情和register刚好相反,从缓存中清除所有和当前监听对象相关的producers和subscribers。
作 者:ChanghuiN
原文链接:https://cloud.tencent.com/developer/article/1333357
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。