Otto是Event Bus 模式的一種實現, 使用它可使事件的發送與處理解耦, 爲了堅挺某個事件沒必要再去實現相應的接口, 只需簡單的加標註、註冊就能夠實現。java
首先來看兩種標註:app
subscribe:this
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Subscribe { }
produce:spa
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Produce { }
第一個方法標註標識一個方法是事件的消費者(事件的監聽者), 第二個方法標註標識一個方法可以產生事件對象。.net
對於擁有事件監聽方法的對象 以及擁有事件產生方法的對象, 分別有EventHandler 和 EventProducer 對象對其進行包裝:
code
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; } } ... }