最近讲的都是square出品的组件,今天还是继续讲解Square旗下的Otto框架
引用otto官网说的
An enhanced Guava-based event bus with emphasis on Android support.
Otto is an event bus designed to
decouple different parts of your application
while still allowing them to communicate efficiently.
Forked from Guava,
Otto adds unique functionality to an already refined
event bus as well as specializing it to the Android platform.
Otto是基于Google的Guava(没听说过??)的Android事件总线,如果在Android项目中想进行组件的通信可以使用这个库,可以降低程序之间的耦合性。
科普Guava:
Guava是Google基于Java1.6的类库集合扩展项目。
提供了collections,caching,eventbus高质量的API来使你的Java代码更加优美
Guava的EventBus首先实现了一个基于发布订阅的消息类库,默认以注解来查找订阅者
Guava相关资料:
源码包的简单说明:
com.google.common.annotations:普通注解类型。
com.google.common.base:基本工具类库和接口。
com.google.common.cache:缓存工具包,非常简单易用且功能强大的JVM内缓存。
com.google.common.collect:带泛型的集合接口扩展和实现,以及工具类,这里你会发现很多好玩的集合。
com.google.common.eventbus:发布订阅风格的事件总线。
com.google.common.hash: 哈希工具包。
com.google.common.io:I/O工具包。
com.google.common.math:原始算术类型和超大数的运算工具包。
com.google.common.net:网络工具包。
com.google.common.primitives:八种原始类型和无符号类型的静态工具包。
com.google.common.reflect:反射工具包。
com.google.common.util.concurrent:多线程工具包。
Otto已经快要被Square废弃了,引用下官网上的原话
Deprecated!
This project is deprecated in favor of RxJava and RxAndroid.
These projects permit the same event-driven programming model as Otto,
but they’re more capable and offer better control of threading.
If you’re looking for guidance on migrating from Otto to Rx,
this post is a good start.
Square推荐使用RxJava实现RxBus方式来代替Otto。
因为原来的项目是用的是otto,至少目前otto没有被开发者抛弃。
本文还是介绍下Otto的使用以及原理。
Otto使用姿势
- 首先引入AAR包
// Otto
compile 'com.squareup:otto:1.3.8'
- 构造Bus单例
public class BusProvider {
private static final Bus bus = new Bus();
public static Bus getBus(){
return bus;
}
}
```
3.在代码中实现(只是举个例子,Otto可以不在同一个类中进行通信)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) this.findViewById(R.id.post_event);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 发送事件
BusEvent busEvent = new BusEvent("TODO");
BusProvider.getBus().post(busEvent);
}
});
}
@Override
protected void onResume() {
super.onResume();
// 注册事件
BusProvider.getBus().register(this);
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
// 注销事件
BusProvider.getBus().unregister(this);
}
/**
* 接收事件
* @param event
*/
@Subscribe
public void getEventBus(BusEvent event) {
String key = event.getEventKey();
Toast.makeText(MainActivity.this,"key = " + key,Toast.LENGTH_LONG).show();
}
}
上述看到了其实用法很简单,就是注册,注销,发送事件,接收事件。
> 这里需要提到一点,发送跟接受可以不再同一个类中,但是接受的地方一定要注册时间和注销事件。
#### 重要知识点
定义Subcribe的方法需要记住
参数类型的数量只允许为1个,则抛出异常
如果第一个参数的类型为接口,则抛出异常
方法的公开类型必须为public,private则抛出异常
定义Produce的方法需要记住
Produce的参数如果不等于0,则抛出异常
Produce的返回值类型如果为void,否则抛出异常
Produce的返回值类型如果为接口类型,否则抛出异常
Produce的方法的公开类型必须为public,private则抛出异常
##### post时候,会根据传入的参数类型去查找跟他一致的参数类型的@Subcribe方法
> 其实Otto使用的时候条条框框真的很多
`抛出一个问题?Otto是通过什么方法来进行线程间通信的?`
带着问题,我们看下代码
### 代码讲解
老规矩,还是从代码架构来看。这应该是最近看的最少的类了。
.
├── AnnotatedHandlerFinder.java --用来查找存在@Subcribe和@Produce的类的方法
├── Bus.java --对外提供者,提供register,unregister,post等方法
├── DeadEvent.java --发送这个Event则不会进行Post
├── EventHandler.java --@Subcribe的方法和类的实体对象
├── EventProducer.java --@Produce的方法和类的实体对象
├── HandlerFinder.java --查找存在@ Subcribe和@Produce的类的方法的接口
├── Produce.java --Produce注解定义
├── Subscribe.java --Subscribe注解定义
└── ThreadEnforcer.java --线程强迫,默认提供MAIN线程,不是主线程,就抛出异常
#### Bus的构造器
开始要构造Bus的对象
Bus bus = new Bus();
这个其实走的全是默认值,具体默认值有哪些,看下面代码
public Bus() {
this(DEFAULT_IDENTIFIER);
}
public Bus(String identifier) {
this(ThreadEnforcer.MAIN, identifier);
}
public Bus(ThreadEnforcer enforcer) {
this(enforcer, DEFAULT_IDENTIFIER);
}
public Bus(ThreadEnforcer enforcer, String identifier) {
this(enforcer, identifier, HandlerFinder.ANNOTATED);
}
/**
* BUS构造器
* @param enforcer 线程判断,默认MAIN,不是主线程则抛出异常
* @param identifier BUS定义
* @param handlerFinder 查找 @Subcribe和 @Produce的类的方法的实现类
*/
Bus(ThreadEnforcer enforcer, String identifier, HandlerFinder handlerFinder) {
// 默认ThreadEnforcer.MAIN,只允许在主线程
this.enforcer = enforcer;
// 默认定义"default"
this.identifier = identifier;
// 提供查找 @Subcribe和 @Produce的类的方法. 实现下面方法
// Map<Class<?>, EventProducer> findAllProducers(Object listener);
// Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener);
this.handlerFinder = handlerFinder;
}
### BUS的Register方法
Bus bus = new Bus();
bus.register(this)
从代码中看出有什么玄机?
/**
* BUS的注解方法
* @param object
*/
public void register(Object object) {
if (object == null) {
throw new NullPointerException("Object to register must not be null.");
}
// 强迫判断,提供类两个对象,ANY和MAIN,
// MAIN表示当前只允许在主线程
// ANY表示任何线程都是支持
enforcer.enforce(this);
// 获取当前Object对象中@Produce的方法
Map<Class<?>, EventProducer> foundProducers = handlerFinder.findAllProducers(object);
for (Class<?> type : foundProducers.keySet()) {
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) {
// 将@Produce生成的扔给@Subcribe进行运行
dispatchProducerResultToHandler(handler, producer);
}
}
}
// 获取当前Object对象中的@Subcribe的方法
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()) {
// 将@Produce生成的扔给@Subcribe进行运行
dispatchProducerResultToHandler(foundHandler, producer);
}
}
}
}
}
以下介绍如何将类中定义的`@Subcribe`和`@Produce`方法找到
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;
}
// 查找方法是否以@Subscribe注解
if (method.isAnnotationPresent(Subscribe.class)) {
Class<?>[] parameterTypes = method.getParameterTypes();
// 参数类型的数量只允许为1个,则抛出异常
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,private则抛出异常
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();
// Produce的参数如果不等于0,则抛出异常
if (parameterTypes.length != 0) {
throw new IllegalArgumentException("Method " + method + "has @Produce annotation but requires "
+ parameterTypes.length + " arguments. Methods must require zero arguments.");
}
// Produce的返回值类型如果为Void,否则抛出异常
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();
// Return的类型为接口的话,否者抛出异常
if (eventType.isInterface()) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
+ " which is an interface. Producers must return a concrete class type.");
}
// Produce的返回值类型如果为void,否则抛出异常
if (eventType.equals(Void.TYPE)) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation but has no return type.");
}
// 方法的公开类型必须为public,private则抛出异常
if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
throw new IllegalArgumentException("Method " + method + " has @Produce annotation on " + eventType
+ " but is not 'public'.");
}
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);
}
`register就是将各个注册的@Subcribe和@Produce的方法放到缓存里`
### Bus的post方法
就是根据post(Object),根据Object对应的Class去找注册进来的@Subcribe中的方法的参数类型。将一致的方法列表弄成队列,然后依次执行
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) {
// 将Post的参数对应的Subcribe方法中对应的参数的方法放到队列中
enqueueEvent(event, wrapper);
}
}
}
if (!dispatched && !(event instanceof DeadEvent)) {
post(new DeadEvent(this, event));
}
// 将上面的队列中保存的方法 依次发送事件
dispatchQueuedEvents();
}
>执行方法(就是通过反射实现的,线程间通信)
>
>重点就是这句 method.invoke(target, 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;
}
}
### Bus的unregister方法
unregister(object)就是从缓存中删除这个object对应的@Subcribe和@Produce的方法
public void unregister(Object object) {
if (object == null) {
throw new NullPointerException("Object to unregister must not be null.");
}
enforcer.enforce(this);
// 清空该Object中的@Produce方法
Map<Class<?>, EventProducer> producersInListener = handlerFinder.findAllProducers(object);
for (Map.Entry<Class<?>, EventProducer> entry : producersInListener.entrySet()) {
final Class<?> key = entry.getKey();
EventProducer producer = getProducerForEventType(key);
EventProducer value = entry.getValue();
if (value == null || !value.equals(producer)) {
throw new IllegalArgumentException(
"Missing event producer for an annotated method. Is " + object.getClass()
+ " registered?");
}
producersByType.remove(key).invalidate();
}
Map<Class<?>, Set<EventHandler>> handlersInListener = handlerFinder.findAllSubscribers(object);
for (Map.Entry<Class<?>, Set<EventHandler>> entry : handlersInListener.entrySet()) {
Set<EventHandler> currentHandlers = getHandlersForEventType(entry.getKey());
Collection<EventHandler> eventMethodsInListener = entry.getValue();
if (currentHandlers == null || !currentHandlers.containsAll(eventMethodsInListener)) {
throw new IllegalArgumentException(
"Missing event handler for an annotated method. Is " + object.getClass()
+ " registered?");
}
for (EventHandler handler : currentHandlers) {
if (eventMethodsInListener.contains(handler)) {
handler.invalidate();
}
}
// 清空该Object中的@Subcribe方法
currentHandlers.removeAll(eventMethodsInListener);
}
}
### 相关资料
[Android 事件总线OTTO用法快速入门](http://blog.csdn.net/zhangweiwtmdbf/article/details/49096615)
[EventBus vs Otto vs Guava--自定义消息总线](http://www.cnblogs.com/avenwu/archive/2015/02/25/4299258.html)
[EventBus & Otto的使用和比较](http://www.jianshu.com/p/cb39a0018db1)
[浅析Otto框架,并与EventBus对比浅析Otto框架,并与EventBus对比](http://mp.weixin.qq.com/s?__biz=MjM5NDkxMTgyNw==&mid=2653057414&idx=1&sn=0fd708aad27ec6184a69d1078964a9e3#wechat_redirect&utm_source=tuicool&utm_medium=referral)
![加油](http:https://img.haomeiwen.com/i1863168/4eed6f8cbdf2d0a0.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
网友评论