Otto是Event Bus 模式的一种实现, 使用它可以使事件的发送与处理解耦, 为了坚挺某个事件不必再去实现相应的接口, 只需简单的加标注、注册就可以实现。
标注:
首先来看两种标注:
subscribe:
1@Retention(RetentionPolicy.RUNTIME) 2@Target(ElementType.METHOD) 3public @interface Subscribe { 4}
produce:
1@Retention(RetentionPolicy.RUNTIME) 2@Target(ElementType.METHOD) 3public @interface Produce { 4}
第一个方法标注标识一个方法是事件的消费者(事件的监听者), 第二个方法标注标识一个方法能够产生事件对象。
包装类:
对于拥有事件监听方法的对象 以及拥有事件产生方法的对象, 分别有EventHandler 和 EventProducer 对象对其进行包装:
EventProducer 的target对象是被包装的对象, 它有一个 具体 @Produce 标注的方法,该方法对象即 method
1class EventProducer { 2 3 /** Object sporting the producer method. */ 4 final Object target; 5 /** Producer method. */ 6 private final Method method; 7 /** Object hash code. */ 8 private final int hashCode; 9 /** Should this producer produce events? */ 10 private boolean valid = true; 11 12 EventProducer(Object target, Method method) { 13 .. 14 15 this.target = target; 16 this.method = method; 17 method.setAccessible(true); 18 19 // Compute hash code eagerly since we know it will be used frequently and we cannot estimate the runtime of the 20 // target's hashCode call. 21 final int prime = 31; 22 hashCode = (prime + method.hashCode()) * prime + target.hashCode(); 23 } 24 25 /** 26 * If invalidated, will subsequently refuse to produce events. 27 * Should be called when the wrapped object is unregistered from the Bus. 28 */ 29 public void invalidate() { 30 valid = false; 31 } 32 33 /** 34 * Invokes the wrapped producer method. 35 */ 36 public Object produceEvent() throws InvocationTargetException { 37 if (!valid) { 38 throw new IllegalStateException(toString() + " has been invalidated and can no longer produce events."); 39 } 40 try { 41 return method.invoke(target); 42 } catch (IllegalAccessException e) { 43 throw new AssertionError(e); 44 } catch (InvocationTargetException e) { 45 if (e.getCause() instanceof Error) { 46 throw (Error) e.getCause(); 47 } 48 throw e; 49 } 50 } 51 52 ... 53 54}
EventHander:
这里的 target 具有一个加了 @Subscribe 标注的 方法, 由method引用
1class EventHandler { 2 3 /** Object sporting the handler method. */ 4 private final Object target; 5 /** Handler method. */ 6 private final Method method; 7 /** Object hash code. */ 8 private final int hashCode; 9 /** Should this handler receive events? */ 10 private boolean valid = true; 11 12 EventHandler(Object target, Method method) { 13 ... 14 15 this.target = target; 16 this.method = method; 17 method.setAccessible(true); 18 19 // Compute hash code eagerly since we know it will be used frequently and we cannot estimate the runtime of the 20 // target's hashCode call. 21 final int prime = 31; 22 hashCode = (prime + method.hashCode()) * prime + target.hashCode(); 23 } 24 25 /** 26 * Invokes the wrapped handler method to handle {@code event}. 27 */ 28 public void handleEvent(Object event) throws InvocationTargetException { 29 if (!valid) { 30 throw new IllegalStateException(toString() + " has been invalidated and can no longer handle events."); 31 } 32 try { 33 method.invoke(target, event); 34 } catch (IllegalAccessException e) { 35 throw new AssertionError(e); 36 } catch (InvocationTargetException e) { 37 if (e.getCause() instanceof Error) { 38 throw (Error) e.getCause(); 39 } 40 throw e; 41 } 42 } 43 44 ... 45 46}