Otto源码分析
来源:互联网 发布:来深圳做销售知乎 编辑:程序博客网 时间:2024/05/22 07:12
构造函数
使用Otto通常是通过一个Provider提供一个Bus单例。首先我们来分析一下Bus的构造函数,Bus类的构造函数最终都会调用Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder)这个构造函数。
其中enforcer用来限制执行register,unregister以及post event的线程,如果执行这些函数的线程不是enforcer指定的线程,就会抛出异常。
identifier相当于给Bus起的一个名字,在toString方法中使用。
handlerFinder是整个event bus的核心,用于在register,unregister的时候寻找所有的subscriber和producer。handlerFinder不需要用户指定,默认使用HandlerFinder接口中定义的常量ANNOTATED,ANNOTATED本身就是HandlerFinder的匿名实现。
注册
如果一个类对某些事件感兴趣,需要调用register方法来注册监听这些事件,监听通过在方法上使用@Subscribe来实现,Otto通过方法的参数来决定是否调用该方法。register方法首先会调用handlerFinder的findAllProducers(object)方法去找到所有使用了@Produce注解的方法。findAllProducers其实是委托AnnotatedHandlerFinder.findAllProducers方法。在AnnotatedHandlerFinder中,定义了一个静态变量SUBSCRIBERS_CACHE
private static final Map<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE = new HashMap<Class<?>, Map<Class<?>, Method>>();
PRODUCERS_CACHE 的key是监听类,就是调用bus.register()的类,value本身又是一个map,这个map的key是事件的class,value是生产事件的方法。
比如下面这个例子:
public class MainActivity extends Activity { @Inject Bus bus; @Override public void onResume() { bus.register(this); } @Produce public ClickEvent produceClick() { // TODO: React to the event somehow! return new ClickEvent(); }}
在PRODUCERS_CACHE中就会有一条记录,它的key是MainActivity.class,value对应的map中,key是ClickEvent.class,value是produceClick Method对象。
SUBSCRIBERS_CACHE:
MainActivity.class -》
ClickEvent.class -》produceClick
当调用AnnotatedHandlerFinder的findAllProducers方法时,会先根据传入的对象的类型,检查是否已经被缓存到PRODUCERS_CACHE,如果没有的话,就会调用loadAnnotatedMethods,利用反射去寻找所有使用了@Produce注解的方法,并且将结果缓存到PRODUCERS_CACHE中。最后,会从PRODUCERS_CACHE中取出监听类的所有Produce方法,遍历这些方法,为一个方法构建一个EventProducer对象,并将这个EventProducer对象放到一个以事件的class作为key的map中,然后返回这个map。EventProducer类包含了Produce方法和该方法所属的对象,并且提供了调用Produce方法的功能。
回到Bus的Register方法,调用完findAllProducers方法之后,会遍历传入的监听类的Produce方法,并且根据Produce方法的返回值类型,来检查是否已经有对应的Subscribe存在,如果有的话,就会调用Subscribe方法,并将Producer的返回值传入。
Set<EventHandler> handlers = handlersByType.get(type);if (handlers != null && !handlers.isEmpty()) { for (EventHandler handler : handlers) { dispatchProducerResultToHandler(handler, producer); }}这里需要注意的是,Bus对象两个map类型的常量,用来缓存所有事件的Producer和Subscriber。
/** All registered event handlers, indexed by event type. */private final ConcurrentMap<Class<?>, Set<EventHandler>> handlersByType = new ConcurrentHashMap<Class<?>, Set<EventHandler>>();/** All registered event producers, index by event type. */private final ConcurrentMap<Class<?>, EventProducer> producersByType = new ConcurrentHashMap<Class<?>, EventProducer>();从定义我们可以看出,一种事件只能有一个Producer,却可以有多个Subscriber。
找到了所有的producers之后,就是调用handlerFinder.findAllSubscribers(object)来寻找object中使用@Subscribe注解的方法,过程和findAllProducers类似,唯一的不同是一个事件可以有多个subscriber,因此findAllSubscribers的返回值类型是Map<Class<?>, Set<EventHandler>>。其中EventHandler包含了subscribe方法和订阅事件的对象的信息。
找到监听类所有的subscribe方法之后,就需要查看bus中时候有和这些subscribe方法对应的producer方法,如果有的话,就会使用调用subscribe方法。这也就是文档上说的,一旦有新的subscriber订阅了某一事件,并且该事件有对应的producer,那么subscriber方法就会被立即调用,并且传入producer方法的返回值。
发送事件
post(Obejct event)方法用来发送事件给所有订阅者,它接收一个Object类型的参数,说明Otto的事件可以是任意类型的对象。post方法首先会获取所有event对象的父类Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());然后遍历这些父类,找到他们的所有订阅者,发送事件。这表明任何订阅了event对象父类的订阅者也都会收到event事件。值得注意的是Otto使用ThreadLocal类型来存放事件队列ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>> eventsToDispatch,这样极大的简化了多线程模式下的开发。
取消订阅
unregister方法,做的事情和register刚好想法,从缓存中清除所有和当前监听对象相关的producers和subscribers。 2 0
- otto源码分析
- Otto源码分析
- Android:Otto源码分析
- Otto的使用和源码分析
- 52.otto 源码解析
- Otto源码初探
- Otto源码详解
- otto源代码分析
- [Android] Otto源码简析
- [Android] Otto源码简析
- 【FastDev4Android框架开发】消息总线EventBus源码分析以及与Otto框架对比(二十一)
- 开源框架研究----Otto源代码分析
- Android 事件总线OTTO使用说明和源码解析
- Android事件总线(四)源码解析otto
- Android事件总线(四)源码解析otto
- Otto介绍
- Otto介绍
- Otto介绍
- 通知(Notification)
- 高级js代码
- Python中的string模块详解——string的中文API文档
- 搜索框
- ioss 8.1 to 8.2 api differences
- Otto源码分析
- Java中泛型二分查找,继承Comparable接口
- 几种常用的JS类定义方法
- Android环境搭建--Eclipse安装错误
- UVA - 11464 Even Parity 枚举+递推
- 自定义注解
- 重载和覆盖
- 不区分大小写的strCaseStr---改造strstr
- 用Rational Rose逆向工程(java)生成类图(教程和错误解决)