您的位置:首页 > 其它

Otto的使用和源码分析

2015-08-11 13:53 274 查看

Otto

Otto是square的一个event bus实现。

Event bus是一款针对Android优化的发布/订阅事件总线,主要功能是替代Intent、Handler、BroadCast

在Activity、Fragment、Service、Thread之间传递消息。其优点是开销小,代码更优雅,以及

将发送者和接收者解耦。

下载

在Android studio的module级别的build.gradle中dependencies下加入

compile 'com.squareup:otto:1.3.8'


使用

1.新建一个Bus实例,建议使用单例。

java

Bus bus = new Bus();


2.事件发布是非常重要的,因为它可以通知相应事件的订阅者某个动作已经发生。任何的类实例都可以

通过Bus发布事件,并且只有订阅了该事件的订阅者才会收到相应通知。

通过post方法发布一个新的事件

java

bus.post(new AnswerAvailableEvent(42));


除此之外,还有另外一种方法可以发布事件,这种形式会在Bus调用register方法时立即发布事件。

java

@Produce

public AnswerAvailableEvent produceAnswer() {

// Assuming 'lastAnswer' exists.

return new AnswerAvailableEvent(this.lastAnswer);

}


在方法级别上添加@Produce注解,方法的访问权限一定得是public的,并且其返回值类型是所发布

的事件类型。

这种事件发布形式还必需得在类实例中注册Bus实例

java

bus.register(this);


否则这个事件是无法让其订阅者接收到事件通知的。

3.订阅一个事件,你需要在方法级别上添加一个@Subscribe的注解。这个方法只能带有一个参数,

并且类型是你需要的订阅事件类型。

订阅一个事件,需要这样做

java

@Subscribe

public void answerAvailable(AnswerAvailableEvent event) {

// TODO: React to the event somehow!

}


需要注意的是,上面的方法其访问权限一定得是public的,其他无限制。

为了能够接收到事件,类实例需要注册Bus。通过下面方式注册

java

bus.register(this);


我们可以在适当的时候调用unregister方法取消Bus的注册

java

bus.unregister(this);


我们可以在Activity和Fragment的OnResume方法中注册Bus,然后在OnPause方法中取消注册。

4.默认的,新建的Bus是在主线程上活动的。

java

Bus bus1 = new Bus();

Bus bus2 = new Bus(ThreadEnforcer.MAIN);


上面两句代码是等价的。

你还可以实例化一个在任何线程都可以活动的Bus,

java

Bus bus3 = new Bus(ThreadEnforcer.ANY);


5.对于上面的使用方法,我是参照官方文档做一个大概的说明。大家可以使用git clone下官方提供

的sample研究具体的使用方法。

链接: https://github.com/square/otto

源码分析

Otto的源码只有九个类,阅读起来还是很容易理解的。

先看@Produce、@Subscribe这两个注解的定义。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Produce {

}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Subscribe {

}


可以看出这两个注解都是在jvm运行时可获得的,并且都是作用在方法级别上。

再来看ThreadEnforcer、HandlerFinder两个接口。

public interface ThreadEnforcer {

/**
* 强制bus在某个确定的线程
*/
void enforce(Bus bus);

/** A {@link ThreadEnforcer} that does no verification. */
ThreadEnforcer ANY = new ThreadEnforcer() {
@Override public void enforce(Bus bus) {
// Allow any thread.
}
};

/** A {@link ThreadEnforcer} that confines {@link Bus} methods to the main thread. */
ThreadEnforcer MAIN = new ThreadEnforcer() {
@Override public void enforce(Bus bus) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("Event bus " + bus +
" accessed from non-main thread " + Looper.myLooper());
}
}
};

}


ThreadEnforcer里面提供了两个默认的实现,其中我们新创建的Bus实例是默认使用Android的主线程的。

/** Finds producer and subscriber methods. */
interface HandlerFinder {

Map<Class<?>, EventProducer> findAllProducers(Object listener);

Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener);

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);
}
};
}


HandlerFinder是用于查找使用了@Produce和@Subscribe的方法及事件类型的的。从方法定义就可以看出,一个

类中只能存在一个通过@Produce发布事件的方法,却可以存在多个使用@Subscribe的方法,即事件订阅者。

同样的,HandlerFinder里面也提供了一个默认的实现,委派AnnotatedHandlerFinder进行具体的操作。

其中,EventProducer的代码实现如下

class EventProducer {

/** Object sporting the producer method. */
final Object target;
/** Producer method. */
private final Method method;

EventProducer(Object target, Method method) {
if (target == null) {
throw new NullPointerException("EventProducer target cannot be null.");
}
if (method == null) {
throw new NullPointerException("EventProducer method cannot be null.");
}

this.target = target;
this.method = method;

/** 抑制java对修饰符访问权限的检查,提高jdk的反射效率 */
method.setAccessible(true);

...
}

/**
* 通过反射调用方法
*/
public Object produceEvent() throws InvocationTargetException {
if (!valid) {
throw new IllegalStateException(toString() + " has been invalidated and can no longer produce events.");
}
try {
return method.invoke(target);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Error) {
throw (Error) e.getCause();
}
throw e;
}
}

// 重写toString()、hashCode()、equals()方法
}


EventHandler类的代码也差不多。

再来看看AnnotatedHandlerFinder到底干了哪些事。

final class AnnotatedHandlerFinder {

/*
* 用于保存使用了@Produce注解的类及方法,其中map的键是监听类,值是一个map,值的map的
* 键是事件类型,值是方法
*/
private static final ConcurrentMap<Class<?>, Map<Class<?>, Method>> PRODUCERS_CACHE =
new ConcurrentHashMap<Class<?>, Map<Class<?>, Method>>();

/** 用于保存使用了@Subscribe注解的类及方法 */
private static final ConcurrentMap<Class<?>, Map<Class<?>, Set<Method>>> SUBSCRIBERS_CACHE =
new ConcurrentHashMap<Class<?>, Map<Class<?>, Set<Method>>>();

/** 加载使用了@Produce注解的类及方法 */
private static void loadAnnotatedProducerMethods(Class<?> listenerClass,
Map<Class<?>, Method> producerMethods) {
Map<Class<?>, Set<Method>> subscriberMethods = new HashMap<Class<?>, Set<Method>>();
loadAnnotatedMethods(listenerClass, producerMethods, subscriberMethods);
}

/** 加载使用了@Subscribe注解的类及方法 */
private static void loadAnnotatedSubscriberMethods(Class<?> listenerClass,
Map<Class<?>, Set<Method>> subscriberMethods) {
Map<Class<?>, Method> producerMethods = new HashMap<Class<?>, Method>();
loadAnnotatedMethods(listenerClass, producerMethods, subscriberMethods);
}

/**
* 加载所有使用了@Produce和@Subscribe注解的方法
*/
private static void loadAnnotatedMethods(Class<?> listenerClass,
Map<Class<?>, Method> producerMethods, Map<Class<?>, Set<Method>> subscriberMethods) {
for (Method method : listenerClass.getDeclaredMethods()) {
// The compiler sometimes creates synthetic bridge methods as part of the
// type erasure process. As of JDK8 these methods now include the same
// annotations as the original declarations. They should be ignored for
// subscribe/produce.
if (method.isBridge()) {
continue;
}
if (method.isAnnotationPresent(Subscribe.class)) {
Class<?>[] parameterTypes = method.getParameterTypes();

/** 参数个数判断 */
if (parameterTypes.length != 1) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation but requires "
+ parameterTypes.length + " arguments.  Methods must require a single argument.");
}

Class<?> eventType = parameterTypes[0];

/** 判断是否为接口 */
if (eventType.isInterface()) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
+ " which is an interface.  Subscription must be on a concrete class type.");
}

/** 判断方法的访问权限是否为public */
if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
throw new IllegalArgumentException("Method " + method + " has @Subscribe annotation on " + eventType
+ " but is not 'public'.");
}

Set<Method> methods = subscriberMethods.get(eventType);
if (methods == null) {
methods = new HashSet<Method>();
subscriberMethods.put(eventType, methods);
}
methods.add(method);
} else if (method.isAnnotationPresent(Produce.class)) {
Class<?>[] parameterTypes = method.getParameterTypes();

/** 参数个数判断 */
if (parameterTypes.length != 0) {
throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires "
+ parameterTypes.length + " arguments.  Methods must require zero arguments.");
}

/** 方法返回类型是否为Void.class判断 */
if (method.getReturnType() == Void.class) {
throw new IllegalArgumentException("Method " + method
+ " has a return type of void.  Must declare a non-void type.");
}

Class<?> eventType = method.getReturnType();

/** 是否为接口判断 */
if (eventType.isInterface()) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
+ " which is an interface.  Producers must return a concrete class type.");
}

/** 方法返回值判断 */
if (eventType.equals(Void.TYPE)) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation but has no return type.");
}

/** 判断方法的访问权限是否为public */
if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
+ " but is not 'public'.");
}

/** 判断此类事件是否已经由@Produce发布过 */
if (producerMethods.containsKey(eventType)) {
throw new IllegalArgumentException("Producer for type " + eventType + " has already been registered.");
}
producerMethods.put(eventType, method);
}
}

/** 把查找到的分别放进缓存 */
PRODUCERS_CACHE.put(listenerClass, producerMethods);
SUBSCRIBERS_CACHE.put(listenerClass, subscriberMethods);
}

/** 查找所有的@Produce */
static Map<Class<?>, EventProducer> findAllProducers(Object listener) {
final Class<?> listenerClass = listener.getClass();
Map<Class<?>, EventProducer> handlersInMethod = new HashMap<Class<?>, EventProducer>();

Map<Class<?>, Method> methods = PRODUCERS_CACHE.get(listenerClass);
/** 如果缓存中不存在 */
if (null == methods) {
methods = new HashMap<Class<?>, Method>();
loadAnnotatedProducerMethods(listenerClass, methods);
}
if (!methods.isEmpty()) {
for (Map.Entry<Class<?>, Method> e : methods.entrySet()) {
/** 包装到EventProducer */
EventProducer producer = new EventProducer(listener, e.getValue());
handlersInMethod.put(e.getKey(), producer);
}
}

return handlersInMethod;
}

/** 查找所有的@Subscribe */
static Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {
...
}

private AnnotatedHandlerFinder() {
// No instances.
}

}


阅读AnnotatedHandlerFinder之后,可以很清楚地知道它主要是负责查找指定类中带有@Produce

和@Subscribe注解的方法,并且把相应的事件类型放到相应的缓存中。

其中HandlerFinder的默认实现ANNOTATED就是使用了AnnotatedHandlerFinder.findAllProducers(listener)

和AnnotatedHandlerFinder.findAllSubscribers(listener)来完成具体的注解查找工作的。

最后只剩下最重要的Bus类了。

因为我们使用Otto是从在Activity或Fragment的OnResume方法中进行register()开始的,所有我们

看看register()到底干了什么事。

public void register(Object object) {
if (object == null) {
throw new NullPointerException("Object to register must not be null.");
}
/** 确认所在线程 */
enforcer.enforce(this);

/** 查找所有的@Produce */
Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
for (Class<?> type : foundProducers.keySet()) {

/** 判断是否当前类已经存在一个使用@Produce的方法 */
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);
}
}
}

/** 查找所有的@Subscribe */
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);
}
}
}
}
}


到了这里,我们已经很清楚了,register方法主要是查找所有的@Produce和@Subscribe并且进行事件

分发给handler处理。

private void dispatchProducerResultToHandler(EventHandler handler, EventProducer producer) {
Object event = null;
try {
/** 通过反射调用方法,前面已经在EventProducer分析过,发布@Produce的事件 */
event = producer.produceEvent();
} catch (InvocationTargetException e) {
throwRuntimeException("Producer " + producer + " threw an exception.", e);
}
if (event == null) {
return;
}
/** 再次分发事件 */
dispatch(event, handler);
}

protected void dispatch(Object event, EventHandler wrapper) {
try {
/** 通过反射调用方法,前面已经在EventHandler分析过,这里就是接收到事件通知之后执行具体的操作,执行@Subscribe的方法 */
wrapper.handleEvent(event);
} catch (InvocationTargetException e) {
throwRuntimeException(
"Could not dispatch event: " + event.getClass() + " to handler " + wrapper, e);
}
}


至于unregister和register方法则是相反的操作,移除当前类及方法的监听。

当我们调用post发布事件又发生了什么事呢?

下面我们来看看post方法的实现。

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);
}
}
}

/** 没有订阅者的事件没有被分发,被封装成DeadEvent再次post出去 */
if (!dispatched && !(event instanceof DeadEvent)) {
post(new DeadEvent(this, event));
}

/** 逐一分发事件队列的事件方法 */
dispatchQueuedEvents();
}

protected void enqueueEvent(Object event, EventHandler handler) {
eventsToDispatch.get().offer(new EventWithHandler(event, handler));
}

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);
}
}


最后,整个Otto的源码分析过程就完成了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: