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