OTTO是Square推出的库,地址:https://github.com/square/otto
先来看看otto的官方介绍
An enhanced Guava-based event bus with emphasis on Android support.Otto is an event bus designed to decouple different parts of your application while still allowing them to communicate efficiently.Forked from Guava, Otto adds unique functionality to an already refined event bus as well as specializing it to the Android platform.
OTTO基于Guava项目的Android支持库,如果你在Android程序开发的过程中想要不同的组件之间进行有效的通信可以使用这个库。通过otto库可以。
public class AppConfig { private static final Bus BUS = new Bus(); public static Bus getInstance() { return BUS; } }
在类创建好之后,或者需要重新注册的时候注册,一般在Activity的onCreate()或者onPause()方法中
AppConfig.getBusInstance().register(this);
@Subscribe public void onWallpaperUpdate(MyObject obj) { //对obj进行需要的逻辑处理 }
AppConfig.getBusInstance().post(myobj);
注意在类销毁的时候或者暂时不需要再收消息的时候解绑,,一般在Activity的onDestroy()或者onResume()方法中
AppConfig.getBusInstance().unregister(this);
public Bus() { this(DEFAULT_IDENTIFIER); } public Bus(String identifier) { this(ThreadEnforcer.MAIN, identifier); } public Bus(ThreadEnforcer enforcer) { this(enforcer, DEFAULT_IDENTIFIER); } public Bus(ThreadEnforcer enforcer, String identifier) { this(enforcer, identifier, HandlerFinder.ANNOTATED); } Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder) { this.enforcer = enforcer; this.identifier = identifier; this.handlerFinder = handlerFinder; }我们通常使用Bus()这个构造方法,在整个app中创建一个单例,这样不但节省资源,更重要的是保证消息正常到达如果不是单例,用一个Bus进行了注册,而用另外一个Bus发送消息,这样订阅的方法是无法收到消息的。
public void register(Object object) { if (object == null) { throw new NullPointerException("Object to register must not be null."); } enforcer.enforce(this); 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); } } } Map<Class<?>, Set<EventHandler>> foundHandlersMap = handlerFinder.findAllSubscribers(object); for (Class<?> type : foundHandlersMap.keySet()) { 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); if (!handlers.addAll(foundHandlers)) { throw new IllegalArgumentException("Object already registered."); } } for (Map.Entry<Class<?>, Set<EventHandler>> entry : foundHandlersMap.entrySet()) { Class<?> type = entry.getKey(); EventProducer producer = producersByType.get(type); if (producer != null && producer.isValid()) { Set<EventHandler> foundHandlers = entry.getValue(); for (EventHandler foundHandler : foundHandlers) { if (!producer.isValid()) { break; } if (foundHandler.isValid()) { dispatchProducerResultToHandler(foundHandler, producer); } } } } }对象注册首先进行了非空校验,然后是线程的校验,对象不可为空,不可多次注册
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>();handlersByType的key中保存了订阅方法的入参 参数类型,vaue中保存着订阅者具体的对象和对应方法
public void post(Object event) { if (event == null) { throw new NullPointerException("Event to post must not be null."); } enforcer.enforce(this); Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass()); boolean dispatched = false; for (Class<?> eventType : dispatchTypes) { 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(); }这里主要涉及两个属性
private final ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>> eventsToDispatch = new ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>>() { @Override protected ConcurrentLinkedQueue<EventWithHandler> initialValue() { return new ConcurrentLinkedQueue<EventWithHandler>(); } }; /** True if the current thread is currently dispatching an event. */ private final ThreadLocal<Boolean> isDispatching = new ThreadLocal<Boolean>() { @Override protected Boolean initialValue() { return false; } };当调用 public void post(Object event)这个方法之后,首先进行线程校验,然后解析出对应的订阅者,如果有订阅者,将event放入队列中, 如果没有,就作为一个DeadEvent,对于DeadEvent注释是这样说的
protected void dispatchQueuedEvents() { // don't dispatch if we're already dispatching, that would allow reentrancy and out-of-order events. Instead, leave // the events to be dispatched after the in-progress dispatch is complete. if (isDispatching.get()) { return; } isDispatching.set(true); try { while (true) { EventWithHandler eventWithHandler = eventsToDispatch.get().poll(); if (eventWithHandler == null) { break; } if (eventWithHandler.handler.isValid()) { dispatch(eventWithHandler.event, eventWithHandler.handler); } } } finally { isDispatching.set(false); } }消息队列使用ThreadLocal保证了队列的独立性。同时多个线程会创建多个循环,提高了效率。发送的消息很快就就可以分发。
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(); }跟register类似,首先是对象非空校验,然后是线程校验,然后解绑,注册跟解绑一定要成对, 没有注册不可以解绑,解绑之后不可以直接再次解绑。
/** Cache event bus producer methods for each class. */ private static final ConcurrentMap<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE = new ConcurrentHashMap<Class<?>, Map<Class<?>, Method>>(); /** Cache event bus subscriber methods for each class. */ private static final ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE = new ConcurrentHashMap<Class<?>, Map<Class<?>, Set<Method>>>();