一、Otto简单介绍
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库可以。
二、Otto简单使用
1、创建一个BUS的单例。
public class AppConfig {
private static final Bus BUS = new Bus();
public static Bus getInstance() {
return BUS;
}
}
2、在需要使用Otto的类中注册
在类创建好之后,或者需要重新注册的时候注册,一般在Activity的onCreate()或者onPause()方法中
AppConfig.getBusInstance().register(this);
3、定义订阅方法
@Subscribe
public void onWallpaperUpdate(MyObject obj) {
//对obj进行需要的逻辑处理
}<span style="font-family:SimSun;">
</span>
4、发送消息
AppConfig.getBusInstance().post(myobj);
5、解绑
注意在类销毁的时候或者暂时不需要再收消息的时候解绑,,一般在Activity的onDestroy()或者onResume()方法中
AppConfig.getBusInstance().unregister(this);
三、Otto源码解析
1、整体结构
Bus 总线核心类
DeadEvent 没有接收者的事件
EventHandler 事件订阅者
EventProducer 事件生产者
HandlerFinder 获取接收者生产者
Produce 生产者的注解
Subscribe 订阅者注解
ThreadEnforcer对线程进行校验
2、Bus的关键属性方法分析
(1)构造函数
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发送消息,这样订阅的方法是无法收到消息的。
(2)对象注册
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中保存着订阅者具体的对象和对应方法
所谓有对应生产者,就是有Produce注解的方法返回值参数类型和有Subscribe注解的方法参数相同。
protected void dispatch(Object event, EventHandler wrapper)
(3)消息发送
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注释是这样说的
* <p>Subscribing a DeadEvent handler is useful for debugging or logging, as it can detect misconfigurations in a
* system's event distribution.
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保证了队列的独立性。同时多个线程会创建多个循环,提高了效率。发送的消息很快就就可以分发。
(4)解绑操作
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类似,首先是对象非空校验,然后是线程校验,然后解绑,注册跟解绑一定要成对,
没有注册不可以解绑,解绑之后不可以直接再次解绑。
3、AnnotatedHandlerFinder对注解的解析,构建生产者和订阅者
/** 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>>>();
结构相同,key值是解析对象对应的class,value是方法参数类型(生产者是返回数据类型,订阅者是方法参数的数据类型)和对应方法。
private static void loadAnnotatedProducerMethods(Class<?> listenerClass,Map<Class<?>, Method> producerMethods) ,
private static void loadAnnotatedMethods(Class<?> listenerClass,Map<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods)。
private static void loadAnnotatedSubscriberMethods(Class<?> listenerClass,Map<Class<?>, Set<Method>> subscriberMethods) ,
private static void loadAnnotatedMethods(Class<?> listenerClassMap<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods)。