otto源码分析
来源:互联网 发布:网络被禁用了怎么恢复 编辑:程序博客网 时间:2024/05/16 22:44
otto这个开源项目是一个event bus模式的消息框架,用于程序各个模块之间的通信,此消息框架可以使得各个
模块之间减少耦合性。
此项目是支付公司square一个开源项目,项目托管于github
https://github.com/square/otto
基本模型是,Android的组件可以注册监听,然后发送消息,接收消息,模式就是观察者模式,但是有别于
java实现的观察者模式,otto更具解耦性,通过注解可以现实监听工作。
otto中的总控制中心的类是Bus,复杂事件的注册分发工作。
首先要把需要把监听事件的组件或者发送事件的组件注册进去
调用Bus的register方法
publicvoidregister(Object object)
参数这个对象的所有的事件处理方法(订阅方法)用于处理接受到的事件,生产者方法用于提供事件。
意思是说,这个注册者即可以接收事件,也可以生产事件。
接着说了注册时的一些特殊情况,
(1)如果在注册的时候,订阅了一个事件类型,并且有产生事件的方法,那么会立即调用产生事件的方法,
把事件分发给这个订阅者方法。
(2)如果在注册的时候,产生特定事件的方法已经存在了订阅者,会调用事件产生方法,把事件分发给事件
订阅者。
方法的具体实现分析:
上面的代码用于获取这个被注册对象的所有生产者方法,可以对应于多个事件的生产者方法
一个被注册对象,同一个事件只能注册一个生产者方法。
handlerFinder是HandlerFinder的实例,是Bus的辅助类,用于找到指定被注册者的所有生产者和订阅者方法。
handlerFinder.findAllProducers(object)返回一个map集合,key是事件的Class的实例,value
是EventProducer是对生产者方法和被注册者实例的包装。
从这里可以看出,虽然没有继续看这个方法的代码,可以猜测被注册者对于同一个事件只能有一个生产者。
我们继续跟踪HandlerFinder findAllProducers()方法的代码
HandlerFinder只是一个借口,然后在其内部实现了一个内部类
如下:
会调用到这句代码:
AnnotatedHandlerFinder.findAllProducers(listener)
进去看下代码
我们再回到Bus的register方法
dispatchProducerResultToHandler(handler, producer);
具体实现就是通过反射去调用producer生产出方事件,把事件传递给handler,再通过反射
回调注册的方法。
继续。。。
regeister这个方法解释完了。
在继续看下post(event)方法
这个方法的作用是分发事件到所有注册这个事件的方法
有可能这个事件分发失败,会封装一个DeadEvent对象,然后重新分发,但是这个DeadEvent对象没有被处理。。。
接下来就是注销方法unregister(listener)
删除和这个listener对象相关的生产事件的方法和注册监听的方法
(1)同一个事件只能有一个生产此事件的方法,如果存在多个会报非检查异常,产生此类事件的只允许有一个来源或者说只允许
有一个活者的来源。
(2)同一个事件可以有多个注册监听同一个事件的方法,只要存在就会分发给他们。
(3)按照官方的demo尽量只有一个Bus实例,一是减少内存消耗,也利于分发工作,如果不同的Bus,那么就无法把分发给其他Bus的注册监听的方法了。
这个EventBus消息框架比较适合推送的处理中心对消息的分发工作,可以解耦的方式,分发给程序的各个模块。
square公司还有很多比较好的开源项目,
网络库okhttp初支持http外,还支持spdy,github地址https://github.com/square/okhttp;
处理图片的库picasso(毕加索) ,github地址 https://github.com/square/picasso;
一个日历控件库,包含Android版和iOS版, github地址 https://github.com/square/android-times-square (Android版)。
其它square公司的开源项目:https://github.com/square
模块之间减少耦合性。
此项目是支付公司square一个开源项目,项目托管于github
https://github.com/square/otto
基本模型是,Android的组件可以注册监听,然后发送消息,接收消息,模式就是观察者模式,但是有别于
java实现的观察者模式,otto更具解耦性,通过注解可以现实监听工作。
otto中的总控制中心的类是Bus,复杂事件的注册分发工作。
首先要把需要把监听事件的组件或者发送事件的组件注册进去
调用Bus的register方法
publicvoidregister(Object object)
这个方法的解释是这样的,先看下英文
/** * Registers all handler methods on {@code object} to receive events and producer methods to provide events. * If any subscribers are registering for types which already have a producer they will be called immediately * with the result of calling that producer. * If any producers are registering for types which already have subscribers, each subscriber will be called with * the value from the result of calling the producer. * * @param object object whose handler methods should be registered. * @throws NullPointerException if the object is null. */
参数这个对象的所有的事件处理方法(订阅方法)用于处理接受到的事件,生产者方法用于提供事件。
意思是说,这个注册者即可以接收事件,也可以生产事件。
接着说了注册时的一些特殊情况,
(1)如果在注册的时候,订阅了一个事件类型,并且有产生事件的方法,那么会立即调用产生事件的方法,
把事件分发给这个订阅者方法。
(2)如果在注册的时候,产生特定事件的方法已经存在了订阅者,会调用事件产生方法,把事件分发给事件
订阅者。
方法的具体实现分析:
public void register(Object object) { if (object == null) { throw new NullPointerException("Object to register must not be null."); } //检查是否在主线程中进行了注册的,默认必须在主线程中调用 enforcer.enforce(this); //key是事件的class对象 Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
上面的代码用于获取这个被注册对象的所有生产者方法,可以对应于多个事件的生产者方法
一个被注册对象,同一个事件只能注册一个生产者方法。
handlerFinder是HandlerFinder的实例,是Bus的辅助类,用于找到指定被注册者的所有生产者和订阅者方法。
handlerFinder.findAllProducers(object)返回一个map集合,key是事件的Class的实例,value
是EventProducer是对生产者方法和被注册者实例的包装。
从这里可以看出,虽然没有继续看这个方法的代码,可以猜测被注册者对于同一个事件只能有一个生产者。
我们继续跟踪HandlerFinder findAllProducers()方法的代码
HandlerFinder只是一个借口,然后在其内部实现了一个内部类
如下:
HandlerFinder ANNOTATED = new HandlerFinder() { @Override public Map<Class<?>, EventProducer> findAllProducers(Object listener) { return AnnotatedHandlerFinder.findAllProducers(listener); } @Override public Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) { return AnnotatedHandlerFinder.findAllSubscribers(listener); } };
会调用到这句代码:
AnnotatedHandlerFinder.findAllProducers(listener)
进去看下代码
static Map<Class<?>, EventProducer> findAllProducers(Object listener) { final Class<?> listenerClass = listener.getClass(); Map<Class<?>, EventProducer> handlersInMethod = new HashMap<Class<?>, EventProducer>(); //检查是否不存在此listenerClass的生产者方法,需要找出来放到PRODUCERS_CACHE中 //PRODUCERS_CACHE是一个map,可以是listener的class对象,值是所有的事件生产者方法 if (!PRODUCERS_CACHE.containsKey(listenerClass)) { loadAnnotatedMethods(listenerClass); }//下面的代码就是把所有的生产者方法封装起来,返回给调用者 Map<Class<?>, Method> methods = PRODUCERS_CACHE.get(listenerClass); if (!methods.isEmpty()) { for (Map.Entry<Class<?>, Method> e : methods.entrySet()) { EventProducer producer = new EventProducer(listener, e.getValue()); handlersInMethod.put(e.getKey(), producer); } } return handlersInMethod; }
我们再回到Bus的register方法
//key是事件的class对象 Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object); for (Class<?> type : foundProducers.keySet()) { //下面几行代码用来检查,事件是否已经注册过了,一个类一个事件只能注册一次 final EventProducer producer = foundProducers.get(type); EventProducer previousProducer = producersByType.putIfAbsent(type, producer); //checking if the previous producer existed if (previousProducer != null) { throw new IllegalArgumentException("Producer method for type " + type + " found on type " + producer.target.getClass() + ", but already registered by type " + previousProducer.target.getClass() + "."); } //检查一下注册这个事件的注册者是否存在,存在就回调一下注册者 Set<EventHandler> handlers = handlersByType.get(type); if (handlers != null && !handlers.isEmpty()) { for (EventHandler handler : handlers) { dispatchProducerResultToHandler(handler, producer); } } }这行代码用于回调
dispatchProducerResultToHandler(handler, producer);
具体实现就是通过反射去调用producer生产出方事件,把事件传递给handler,再通过反射
回调注册的方法。
继续。。。
//如果有处理此事件的注册者,回调注册者 Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object); for (Class<?> type : foundHandlersMap.keySet()) { //type变量是事件的class对象 Set<EventHandler> handlers = handlersByType.get(type); if (handlers == null) { //concurrent put if absent Set<EventHandler> handlersCreation = new CopyOnWriteArraySet<EventHandler>(); handlers = handlersByType.putIfAbsent(type, handlersCreation); if (handlers == null) { handlers = handlersCreation; } } final Set<EventHandler> foundHandlers = foundHandlersMap.get(type); handlers.addAll(foundHandlers); }
regeister这个方法解释完了。
在继续看下post(event)方法
这个方法的作用是分发事件到所有注册这个事件的方法
有可能这个事件分发失败,会封装一个DeadEvent对象,然后重新分发,但是这个DeadEvent对象没有被处理。。。
public void post(Object event) { if (event == null) { throw new NullPointerException("Event to post must not be null."); } enforcer.enforce(this); //返回这个event的所有继承关系链的所有class对象(父类class对象和自己) Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass()); //对event家族的所有类的相关注册方法进行调用 boolean dispatched = false; for (Class<?> eventType : dispatchTypes) { //获得和eventType相关的所有注册方法 Set<EventHandler> wrappers = getHandlersForEventType(eventType); //把需要回调处理的注册方法的包装类塞进当前线程处理的队列中去 if (wrappers != null && !wrappers.isEmpty()) { dispatched = true; for (EventHandler wrapper : wrappers) { enqueueEvent(event, wrapper); } } } //没处理的,再分发一次,但是没有发现再次处理的逻辑 if (!dispatched && !(event instanceof DeadEvent)) { post(new DeadEvent(this, event)); } dispatchQueuedEvents(); }
接下来就是注销方法unregister(listener)
删除和这个listener对象相关的生产事件的方法和注册监听的方法
public void unregister(Object object) { if (object == null) { throw new NullPointerException("Object to unregister must not be null."); } enforcer.enforce(this); Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object); for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) { final Class<?> key = entry.getKey(); EventProducer producer = getProducerForEventType(key); EventProducer value = entry.getValue(); if (value == null || !value.equals(producer)) { throw new IllegalArgumentException( "Missing event producer for an annotated method. Is " + object.getClass() + " registered?"); } producersByType.remove(key).invalidate(); } //返回当前对象的所有注册的方法,置为无效并删除掉 Map<Class<?>, Set<EventHandler>> handlersInListener = handlerFinder.findAllSubscribers(object); for (Map.Entry<Class<?>, Set<EventHandler>> entry : handlersInListener.entrySet()) { //返回对应event的所有注册方法的包装类 Set<EventHandler> currentHandlers = getHandlersForEventType(entry.getKey()); Collection<EventHandler> eventMethodsInListener = entry.getValue(); if (currentHandlers == null || !currentHandlers.containsAll(eventMethodsInListener)) { throw new IllegalArgumentException( "Missing event handler for an annotated method. Is " + object.getClass() + " registered?"); } for (EventHandler handler : currentHandlers) { if (eventMethodsInListener.contains(handler)) { handler.invalidate(); } } currentHandlers.removeAll(eventMethodsInListener); } }最后总结一下,
(1)同一个事件只能有一个生产此事件的方法,如果存在多个会报非检查异常,产生此类事件的只允许有一个来源或者说只允许
有一个活者的来源。
(2)同一个事件可以有多个注册监听同一个事件的方法,只要存在就会分发给他们。
(3)按照官方的demo尽量只有一个Bus实例,一是减少内存消耗,也利于分发工作,如果不同的Bus,那么就无法把分发给其他Bus的注册监听的方法了。
这个EventBus消息框架比较适合推送的处理中心对消息的分发工作,可以解耦的方式,分发给程序的各个模块。
square公司还有很多比较好的开源项目,
网络库okhttp初支持http外,还支持spdy,github地址https://github.com/square/okhttp;
处理图片的库picasso(毕加索) ,github地址 https://github.com/square/picasso;
一个日历控件库,包含Android版和iOS版, github地址 https://github.com/square/android-times-square (Android版)。
其它square公司的开源项目:https://github.com/square
1 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介绍
- 我之见--java多线程信号量Semaphore
- apt-get命令
- android上加载opencv模块
- 单例模式的七种写法
- 树之二叉树
- otto源码分析
- Volume 1. Elementary Problem Solving :: Maths - Simple Geometry Uva 10250,579,375,10387,10112
- 常见的c字符串处理函数的源代码以及简单例子【2】
- window sdk 更新
- 复数类
- 观察者模式
- Linxu 下安装 Understand 教程
- 如何利用RSS追踪科学文献
- springmvc validate