EventBus is a central publish/subscribe event system for Android. Events are posted ({@link #post(Object)}) to the bus, which delivers it to subscribers that have a matching handler method for the event type. To receive events, subscribers must register themselves to the bus using {@link #register(Object)}. Once registered, subscribers receive events until {@link #unregister(Object)} is called. Event handling methods must be annotated by {@link Subscribe}, must be public, return nothing (void), and have exactly one parameter (the event).
// This method will be called when a MessageEvent is posted @Subscribe publicvoidonMessageEvent(MessageEvent event){ Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show(); }
// This method will be called when a SomeOtherEvent is posted @Subscribe publicvoidhandleSomethingElse(SomeOtherEvent event){ doSomethingWith(event); }
订阅者同时需要在总线上注册和注销自己。只有当订阅者注册了才能接收到事件。在Android中,通常与 Activity 和 Fragment 的生命周期绑定在一起。
publicstatic EventBus getDefault(){ if (defaultInstance == null) { synchronized (EventBus.class) { if (defaultInstance == null) { defaultInstance = new EventBus(); } } } return defaultInstance; }
单例设计模式,用到了double check。再看看 EventBus 的构造方法:
1 2 3
publicEventBus(){ this(DEFAULT_BUILDER); }
什么,既然是单例模式构造函数还 public ??没错,这样的设计是因为不仅仅可以只有一条总线,还可以有其他的线 (bus) ,订阅者可以注册到不同的线上的 EventBus,通过不同的 EventBus 实例来发送数据,不同的 EventBus 是相互隔离开的,订阅者都只会收到注册到该线上事件。
Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a central bus, consider {@link #getDefault()}.
//赋值buidler(可用户自定义的)给单例的EventBus,如果单例的EventBus不为null了,则抛出异常 public EventBus installDefaultEventBus(){ synchronized (EventBus.class) { if (EventBus.defaultInstance != null) { thrownew EventBusException("Default instance already exists." + " It may be only set once before it's used the first time to ensure consistent behavior."); } EventBus.defaultInstance = build(); return EventBus.defaultInstance; } }
public EventBus build(){ returnnew EventBus(this); }
}
回到 EventBus 的构造方法中:
1 2 3 4 5 6 7 8 9 10 11 12 13
EventBus(EventBusBuilder builder) { subscriptionsByEventType = new HashMap<>();//key为event,value为subscriber列表,这个map就是这个事件有多少的订阅者,也就是事件对应的订阅者 typesBySubscriber = new HashMap<>();//key为subscriber,value为event列表,这个map就是这个订阅者有多少的事件,也就是订阅者订阅的事件列表 stickyEvents = new ConcurrentHashMap<>();//粘性事件 mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);//MainThread的poster backgroundPoster = new BackgroundPoster(this);//Backgroud的poster asyncPoster = new AsyncPoster(this);//Async的poster //订阅者方法寻找类,默认情况下参数是(null, false, false) subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes, builder.strictMethodVerification, builder.ignoreGeneratedIndex); //builder中的赋值 //blablabla...... }
booleancheckAdd(Method method, Class<?> eventType){ // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required. // Usually a subscriber doesn't have methods listening to the same event type. Object existing = anyMethodByEventType.put(eventType, method); if (existing == null) { returntrue; } else { if (existing instanceof Method) { if (!checkAddWithMethodSignature((Method) existing, eventType)) { // Paranoia check // 此时的情况是已经在缓存中有这个method和eventType的,发生情况是子类和父类都是相同事件,相同方法名,切超过3层继承关系 thrownew IllegalStateException(); } // Put any non-Method object to "consume" the existing Method anyMethodByEventType.put(eventType, this); } return checkAddWithMethodSignature(method, eventType); } }
checkAdd 分为两个层级的 check ,第一层级只判断 event type,这样速度快一些;第二层级是多方面判断。anyMethodByEventType 是一个 HashMap ,HashMap.put() 方法返回的是之前的 value ,如果之前没有 value 的话返回的是 null ,通常一个订阅者(包括继承关系)不会有多个相同方法接收同一事件,但是可能会出现子类订阅这个事件的同时父类也订阅了此事件的情况,那么 checkAddWithMenthodSignature() 就排上了用场:
String methodKey = methodKeyBuilder.toString(); Class<?> methodClass = method.getDeclaringClass(); //存储到以methodKey为Key,method的类为value的map中,返回之前methodKey存储的值 Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass); //如果这个值不存在或者这个值是method的类的父类的话,返回true if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) { // Only add if not already found in a sub class returntrue; } else { // Revert the put, old class is further down the class hierarchy subscriberClassByMethodKey.put(methodKey, methodClassOld); returnfalse; } }
publicclassSubscriberMethod{ final Method method; final ThreadMode threadMode; final Class<?> eventType; finalint priority; finalboolean sticky; /** Used for efficient comparison */ String methodString;
int size = subscriptions.size(); for (int i = 0; i <= size; i++) { //根据优先级添加到指定位置 if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) { subscriptions.add(i, newSubscription); break; } } //typesBySubscriber以subscriber为key,eventType的ArrayList为value的HashMap,订阅者订阅的事件列表,找到改订阅者所订阅的所有事件 List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber); if (subscribedEvents == null) { subscribedEvents = new ArrayList<>(); typesBySubscriber.put(subscriber, subscribedEvents); } //添加到该订阅者的所以订阅方法列表中 subscribedEvents.add(eventType); //如果是粘性事件 if (subscriberMethod.sticky) { //是否支持继承关系,就是记录事件的父类(比如事件是ArrayList类型的,那么如果eventInheritance为true的话,会去找为List类型的事件。) if (eventInheritance) { // Existing sticky events of all subclasses of eventType have to be considered. // Note: Iterating over all events may be inefficient with lots of sticky events, // thus data structure should be changed to allow a more efficient lookup // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>). //stickyEvents以eventType为key,event为value的ConcurrentHashMap,Sticky事件保存队列 Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet(); for (Map.Entry<Class<?>, Object> entry : entries) { Class<?> candidateEventType = entry.getKey(); //是否有继承关系 if (eventType.isAssignableFrom(candidateEventType)) { Object stickyEvent = entry.getValue(); //分发事件 checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } } else { Object stickyEvent = stickyEvents.get(eventType); //分发事件 checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } }
首先判断是否有注册过,然后再按照优先级加入到 subscriptionsByEventType 的 value 的 List 中,而 subscriptionsByEventType 是事件订阅者的保存队列,找到该事件所订阅的订阅者以及订阅者的方法、参数等,然后再添加到 typesBySubscriber 的 value 的 List 中,而 typesBySubscriber 是订阅者订阅的事件列表,找到改订阅者所订阅的所有事件,最后判断一下是否是粘性事件,是的话判断事件是否需要考虑继承关系,再分发这个黏性事件。
那么来看一下 checkPostStickyEventToSubscription 这个方法:
1 2 3 4 5 6 7
privatevoidcheckPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent){ if (stickyEvent != null) { // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state) // --> Strange corner case, which we don't take care of here. postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper()); } }
/** For ThreadLocal, much faster to set (and get multiple values). */ finalstaticclassPostingThreadState{ final List<Object> eventQueue = new ArrayList<Object>(); boolean isPosting; boolean isMainThread; Subscription subscription; Object event; boolean canceled; }
PostingThreadState 封装的是当前线程的 post 信息,包括事件队列、是否正在分发中、是否在主线程、订阅者信息、事件实例、是否取消。那么回到 post 方法中: