Otto是Event Bus 模式的一种实现, 使用它可以使事件的发送与处理解耦, 为了坚挺某个事件不必再去实现相应的接口, 只需简单的加标注、注册就可以实现。
标注:
首先来看两种标注:
subscribe:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Subscribe {
}
produce:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Produce {
}
第一个方法标注标识一个方法是事件的消费者(事件的监听者), 第二个方法标注标识一个方法能够产生事件对象。
包装类:
对于拥有事件监听方法的对象 以及拥有事件产生方法的对象, 分别有EventHandler 和 EventProducer 对象对其进行包装:
EventProducer 的target对象是被包装的对象, 它有一个 具体 @Produce 标注的方法,该方法对象即 method
class EventProducer {
/** Object sporting the producer method. */
final Object target;
/** Producer method. */
private final Method method;
/** Object hash code. */
private final int hashCode;
/** Should this producer produce events? */
private boolean valid = true;
EventProducer(Object target, Method method) {
..
this.target = target;
this.method = method;
method.setAccessible(true);
// Compute hash code eagerly since we know it will be used frequently and we cannot estimate the runtime of the
// target's hashCode call.
final int prime = 31;
hashCode = (prime + method.hashCode()) * prime + target.hashCode();
}
/**
* If invalidated, will subsequently refuse to produce events.
* Should be called when the wrapped object is unregistered from the Bus.
*/
public void invalidate() {
valid = false;
}
/**
* Invokes the wrapped producer method.
*/
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;
}
}
...
}
EventHander:
这里的 target 具有一个加了 @Subscribe 标注的 方法, 由method引用
class EventHandler {
/** Object sporting the handler method. */
private final Object target;
/** Handler method. */
private final Method method;
/** Object hash code. */
private final int hashCode;
/** Should this handler receive events? */
private boolean valid = true;
EventHandler(Object target, Method method) {
...
this.target = target;
this.method = method;
method.setAccessible(true);
// Compute hash code eagerly since we know it will be used frequently and we cannot estimate the runtime of the
// target's hashCode call.
final int prime = 31;
hashCode = (prime + method.hashCode()) * prime + target.hashCode();
}
/**
* Invokes the wrapped handler method to handle {@code event}.
*/
public void handleEvent(Object event) throws InvocationTargetException {
if (!valid) {
throw new IllegalStateException(toString() + " has been invalidated and can no longer handle events.");
}
try {
method.invoke(target, event);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Error) {
throw (Error) e.getCause();
}
throw e;
}
}
...
}