Android EventBus3.0使用及源码解析
来源:互联网 发布:初音未来手办淘宝 编辑:程序博客网 时间:2024/04/29 06:18
本文已授权微信公众号《非著名程序员》原创首发,转载请务必注明出处。
叨了个叨
最近因为换工作的一些琐事搞的我一个头两个大,也没怎么去学新东西,实在是有些愧疚。新项目用到了EventBus3.0,原来只是听说EventBus的鼎鼎大名,一直没仔细研究过。趁着周末有些时间,研究下代码,也算没有虚度光阴。
EventBus GitHub : https://github.com/greenrobot/EventBus
EventBus3.0简介
EventBus
是greenrobot出品的一个用于Android中事件发布/订阅的库。以前传递对象可能通过接口、广播、文件等等,尤其像同一个Activity
两个Fragment
之间采用接口传递对象,十分的麻烦,而且耦合度较高。使用EventBus
之后,这些将不再是问题。盗用GiHub上EventBus的一张图。
可以看到,发布者(Publisher
)使用post()
方法将Event
发送到Event Bus
,而后Event Bus
自动将Event
发送到多个订阅者(Subcriber
)。这里需要注意两个地方:(1)一个发布者可以对应多个订阅者。(2)3.0以前订阅者的订阅方法为onEvent()
、onEventMainThread()
、onEventBackgroundThread()
和onEventAsync()
。在Event Bus3.0
之后统一采用注解@Subscribe
的形式,具体实现方式见下文。
EventBus3.0的使用
新建两个Activity
,花3s扫一下即可。代码如下:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册EventBus EventBus.getDefault().register(this); startActivity(new Intent(this,SecondActivity.class)); } @Override protected void onDestroy() { super.onDestroy(); // 反注册EventBus EventBus.getDefault().unregister(this); } // 主线程调用 @Subscribe(threadMode = ThreadMode.MAIN) public void eventBusMain(String str){ Log.i("TAG", "MAIN:"+str+" Thread="+Thread.currentThread().getId()); } // 1.发布线程为主线程,新开线程调用 // 2.发布线程为子线程,发布线程调用 @Subscribe(threadMode = ThreadMode.BACKGROUND) public void eventBusBg(String str){ Log.i("TAG", "BACKGROUND:"+str+" Thread="+Thread.currentThread().getId()); } // 在发布线程调用,默认值 @Subscribe(threadMode = ThreadMode.POSTING) public void eventBusPosting(String str){ Log.i("TAG", "POSTING:"+str+" Thread="+Thread.currentThread().getId()); } // 每次都新开线程调用 @Subscribe(threadMode = ThreadMode.ASYNC) public void eventBusAsync(String str){ Log.i("TAG", "ASYNC:"+str+" Thread="+Thread.currentThread().getId()); }}public class SecondActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); EventBus.getDefault().post("from second activity mainThread: info"); Log.i("TAG", "Post thread="+Thread.currentThread().getId()); new Thread(new Runnable() { @Override public void run() { EventBus.getDefault().post("from second activity childThread: info"); Log.i("TAG", "Post thread="+Thread.currentThread().getId()); } }).start(); }}
在MainActivity
的onCreate()
/onDestroy()
中分别注册/反注册EventBus
。然后写了四个测试ThreadMode
的方法,调用时机注释的很清楚,就不赘述了。最后在SecondActivity
的主线程和子线程中分别调用Post()
方法,注意,这里Post()
方法的参数为Object
类型,这也就意味着我们传递任何对象都是可以的,例如JavaBean
、List<E>
等等都是可以的,这里为了方便演示直接传递了String
。Log信息如下:
第一张图中发布者发送线程为主线程,即Post thread = 1
,在订阅者收到消息时,ThreadMode = Main
和ThreadMode = Posting
的方法都在主线程调用,ASYNC
和BACKGROUND
都新开了线程。图二对比注释同理。
除此之外,Subscribe
注解还支持priority
和sticky
属性。priority
设置接收者的优先级,默认值为0。优先级高的方法先被调用,在方法调用完成后可以调用EventBus.getDefault().cancelEventDelivery(event) ;
终止优先级低的方法的调用。sticky
为粘性事件,默认为关闭状态。能够收到订阅之前发送到的最后一条消息,并且发送的方法不再是post()
而是postSticky()
。
EventBus3.0源码解析
EventBus
是Very的好用。耦合度大大的降低,而且代码十分优雅。它是怎么就做到了这么优雅的呢?知其然,知其所以然。下面就开始一步步的分析。
注解标签Subscribe
对注解不了解的同学可以看下这篇博客。
@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface Subscribe { ThreadMode threadMode() default ThreadMode.POSTING; /** * If true, delivers the most recent sticky event (posted with * {@link EventBus#postSticky(Object)}) to this subscriber (if event available). */ boolean sticky() default false; /** Subscriber priority to influence the order of event delivery. * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of * delivery among subscribers with different {@link ThreadMode}s! */ int priority() default 0;}public enum ThreadMode { POSTING, MAIN, BACKGROUND, ASYNC}
注解Subscribe
在运行时解析,且只能加在METHOD
上。其中有三个方法,threadMode()
返回类型ThreadMode
为枚举类型,默认值为POSTING
,sticky()
默认返回false
,priority()
默认返回0。
1. Register
流程
EventBus#getDefault()
public EventBus() { this(DEFAULT_BUILDER);}public static EventBus getDefault() { if (defaultInstance == null) { synchronized (EventBus.class) { if (defaultInstance == null) { defaultInstance = new EventBus(); } } } return defaultInstance;}
EventBus
采用双重校验锁设计为一个单例模式,奇怪的在于虽然设计为单例模式,但是构造方法确实public
类型,这不是坑爹嘛!难道greenrobot
在设计EventBus
获取实例方法的时候在打LOL,一不小心打错了?原来啊,EventBus
默认支持一条事件总线,通常是通过getDefault()
方法获取EventBus
实例,但也能通过直接new EventBus
这种最简单的方式获取多条事件总线,彼此之间完全分开。设计之思想不禁让人拍案叫绝。
EventBus#register()
public void register(Object subscriber) { Class<?> subscriberClass = subscriber.getClass(); List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } }}
首先得到订阅者的报名.类名,即哪个具体类注册。然后调用subscriberMethodFinder.findSubscriberMethods(subscriberClass)
,从方法名和返回值来看,findSubscriberMethods()
的作用应该是遍历查找订阅者中所有的订阅方法。
SubscriberMethodFinder#findSubscriberMethods()
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) { // 查找缓存 List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass); if (subscriberMethods != null) { // 缓存中有则直接返回 return subscriberMethods; } // 默认false if (ignoreGeneratedIndex) { subscriberMethods = findUsingReflection(subscriberClass); } else { subscriberMethods = findUsingInfo(subscriberClass); } if (subscriberMethods.isEmpty()) { throw new EventBusException("Subscriber " + subscriberClass + " and its super classes have no public methods with the @Subscribe annotation"); } else { // 加入缓存 METHOD_CACHE.put(subscriberClass, subscriberMethods); return subscriberMethods; }}
注意subscriberMethods.isEmpty()
,如果注册了EventBus
,但却没有使用注解Subscribe
是会出现EventBusException
异常的。下面跟进findUsingInfo()
方法。
SubscriberMethodFinder#findUsingInfo()
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) { // 从FIND_STATE_POOL数组中查找FindState,命中返回,否则直接new FindState findState = prepareFindState(); // 初始化FindState findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { findState.subscriberInfo = getSubscriberInfo(findState); // findState.subscriberInfo默认null if (findState.subscriberInfo != null) { SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods(); for (SubscriberMethod subscriberMethod : array) { if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) { findState.subscriberMethods.add(subscriberMethod); } } } else { findUsingReflectionInSingleClass(findState); } // 将findState.clazz变为改类的父类 findState.moveToSuperclass(); } return getMethodsAndRelease(findState);}// SubscriberMethodFinder$FindState#initForSubscriber()void initForSubscriber(Class<?> subscriberClass) { this.subscriberClass = clazz = subscriberClass; skipSuperClasses = false; subscriberInfo = null;}
findState.subscriberInfo
默认null
,那么就进入到findUsingReflectionInSingleClass(findState)
,先看下这个方法,等下还要返回来看。
SubscriberMethodFinder#findUsingReflectionInSingleClass()
private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;private void findUsingReflectionInSingleClass(FindState findState) { Method[] methods; try { // This is faster than getMethods, especially when subscribers are fat classes like Activities // 获取到类中所有的方法 methods = findState.clazz.getDeclaredMethods(); } catch (Throwable th) { // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149 methods = findState.clazz.getMethods(); findState.skipSuperClasses = true; } for (Method method : methods) { // 获取方法的修饰符 int modifiers = method.getModifiers(); // 必须被public修饰,而且不能为MODIFIERS_IGNORE // MODIFIERS_IGNORE定义为ABSTRACT、STATIC、BRIDGE、SYNTHETIC。 if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { // 获取方法所有参数类型 Class<?>[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1) { // 是否有Subscribe注解标签 Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); if (subscribeAnnotation != null) { // 带有Subscribe注解标签的方法的第一个参数类型 Class<?> eventType = parameterTypes[0]; // 关联method, eventType到anyMethodByEventType if (findState.checkAdd(method, eventType)) { ThreadMode threadMode = subscribeAnnotation.threadMode(); // 构造SubscriberMethod,并且添加到findState.subscriberMethods findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(), subscribeAnnotation.sticky())); } } // strictMethodVerification 默认为false,不会抛出异常,但还是建议符合规范 } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) { String methodName = method.getDeclaringClass().getName() + "." + method.getName(); throw new EventBusException("@Subscribe method " + methodName + "must have exactly 1 parameter but has " + parameterTypes.length); } } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) { String methodName = method.getDeclaringClass().getName() + "." + method.getName(); throw new EventBusException(methodName + " is a illegal @Subscribe method: must be public, non-static, and non-abstract"); } }}// `SubscriberMethodFinder#checkAdd()`boolean checkAdd(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) { return true; } else { ...}
接下来返回SubscriberMethodFinder#findUsingInfo()
接着看,在findUsingInfo()
中循环执行完后return getMethodsAndRelease(findState)
static class FindState { final List<SubscriberMethod> subscriberMethods = new ArrayList<>(); ...}private List<SubscriberMethod> getMethodsAndRelease(FindState findState) { List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods); // 置空findState findState.recycle(); synchronized (FIND_STATE_POOL) { for (int i = 0; i < POOL_SIZE; i++) { if (FIND_STATE_POOL[i] == null) { FIND_STATE_POOL[i] = findState; break; } } } return subscriberMethods;}
在getMethodsAndRelease()
中将findState
置空,存放进FIND_STATE_POOL
数组,最后返回findState.subscriberMethods
。返回EventBus#register()
。
EventBus#register()
public void register(Object subscriber) { Class<?> subscriberClass = subscriber.getClass(); List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } }}
调用SubscriberMethodFinder#findSubscriberMethods()
后,以List<SubscriberMethod>
形式返回了订阅者所有的订阅事件。然后遍历执行subscribe()
方法。看样子应该是遍历List<SubscriberMethod>
,然后将订阅者和订阅事件绑定。没撒好说的,跟进subscribe()
EventBus#subscribe()
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { // 获取订阅事件的类型,即订阅方法中的唯一参数类型 Class<?> eventType = subscriberMethod.eventType; // 用订阅者和订阅方法构造一个Subscription对象 Subscription newSubscription = new Subscription(subscriber, subscriberMethod); // 查找所有的订阅了订阅事件的订阅者 CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); // 没有订阅者订阅过则新建个CopyOnWriteArrayList<subscriptions>,并put进subscriptionsByEventType PS:CopyOnWriteArrayList支持并发读写 if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList<>(); subscriptionsByEventType.put(eventType, subscriptions); } else { // 订阅者List不为空,而且已经包含了newSubscription,则会抛出异常。即:订阅者不能重复订阅同一事件 if (subscriptions.contains(newSubscription)) { throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType); } } int size = subscriptions.size(); // 根据订阅者优先级,增加到订阅者列表subscriptions的相应位置 for (int i = 0; i <= size; i++) { if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) { subscriptions.add(i, newSubscription); break; } } // 获取订阅者所有订阅事件的列表,默认为null List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber); if (subscribedEvents == null) { subscribedEvents = new ArrayList<>(); typesBySubscriber.put(subscriber, subscribedEvents); } // 将订阅事件添加进对应订阅者的订阅列表 subscribedEvents.add(eventType); // sticky默认为false if (subscriberMethod.sticky) { 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>). 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); } }}
EventBus#Register()
其实只做了三件事:
1. 查找订阅者所有的订阅事件
2. 将订阅事件作为key
,所有订阅了此订阅事件的订阅者作为value
存放进subscriptionsByEventType
3. 将订阅者作为key
,订阅者的所有订阅事件作为value
存放进typesBySubscriber
至此,EventBus.getDefault().register(this)
流程完毕。
2. Post
流程
EventBus#getDefault()
获取EventBus实例
。和Register
流程中一样,不再赘述。
EventBus#post()
/** Posts the given event to the event bus. */public void post(Object event) { // 依据不同的线程获取相应的刚初始化的PostingThreadState PostingThreadState postingState = currentPostingThreadState.get(); List<Object> eventQueue = postingState.eventQueue; // 将event加入到postingState.eventQueue eventQueue.add(event); // isPosting默认false if (!postingState.isPosting) { // 判断是否是主线程 postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper(); postingState.isPosting = true; if (postingState.canceled) { throw new EventBusException("Internal error. Abort state was not reset"); } try { // 遍历发送eventQueue中的event while (!eventQueue.isEmpty()) { postSingleEvent(eventQueue.remove(0), postingState); } } finally { postingState.isPosting = false; postingState.isMainThread = false; } }}
上面代码中currentPostingThreadState
为ThreadLocal<PostingThreadState>
对象,对ThreadLocal<>
机制不了解的同学,可以查看这篇博客。下面跟进postSingleEvent()
方法。
EventBus#postSingleEvent()
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { // 获取event的类型 Class<?> eventClass = event.getClass(); boolean subscriptionFound = false; // eventInheritance默认为true if (eventInheritance) { // 依据订阅事件类型,将订阅事件类型及所有父类添加进eventTypes。详情见下文EventBus.lookupAllEventTypes()分析 List<Class<?>> eventTypes = lookupAllEventTypes(eventClass); int countTypes = eventTypes.size(); // 遍历countTypes,通过调用postSingleEventForEventType()方法通知所有订阅者 for (int h = 0; h < countTypes; h++) { Class<?> clazz = eventTypes.get(h); subscriptionFound |= postSingleEventForEventType(event, postingState, clazz); } } else { subscriptionFound = postSingleEventForEventType(event, postingState, eventClass); } if (!subscriptionFound) { if (logNoSubscriberMessages) { Log.d(TAG, "No subscribers registered for event " + eventClass); } if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) { post(new NoSubscriberEvent(this, event)); } }}
EventBus#lookupAllEventTypes()
private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) { synchronized (eventTypesCache) { // 根据订阅事件查找所有自身及父类,eventTypes默认为null List<Class<?>> eventTypes = eventTypesCache.get(eventClass); if (eventTypes == null) { eventTypes = new ArrayList<>(); Class<?> clazz = eventClass; while (clazz != null) { // 将订阅事件添加进eventTypes eventTypes.add(clazz); // 遍历订阅事件的所有父类,依次添加进eventTypes addInterfaces(eventTypes, clazz.getInterfaces()); clazz = clazz.getSuperclass(); } // 将订阅事件和包含订阅事件自身及所有父类的eventTypes添加进eventTypesCache eventTypesCache.put(eventClass, eventTypes); } return eventTypes; }}
现在假设传递的数据为Person
类,而Person
类实现了IPerson
接口。通过上面的分析可以得出结论:在传递对象(Person
)的时候,订阅事件中参数为被传递对象的所有父类订阅事件(IPerson
)也都会被调用。笔者已经验证通过,感兴趣的同学可以再验证一下。
EventBus#postSingleEventForEventType()
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) { CopyOnWriteArrayList<Subscription> subscriptions; synchronized (this) { // 根据订阅事件查找所有已经注册过的订阅者 // 注意:这里第一次传递进来的是订阅事件,之后会逐个传递进来订阅事件的父类 subscriptions = subscriptionsByEventType.get(eventClass); } if (subscriptions != null && !subscriptions.isEmpty()) { for (Subscription subscription : subscriptions) { postingState.event = event; postingState.subscription = subscription; boolean aborted = false; try { // 参数解释:subscription-被遍历到的订阅者;event-订阅事件参数(子类); postToSubscription(subscription, event, postingState.isMainThread); aborted = postingState.canceled; } finally { postingState.event = null; postingState.subscription = null; postingState.canceled = false; } if (aborted) { break; } } return true; } return false;}
在EventBus#register()
最后总结道:将订阅事件作为key
,所有订阅了此订阅事件的订阅者作为value
存放进subscriptionsByEventType
。这里就依据订阅事件然后查找对应所有的订阅者。注意:由于遍历订阅事件参数所有父类的原因,一个订阅事件的Post
第一次执行postToSubscription()
时,subscription
参数,遍历时为订阅事件的订阅者。之后再调用postToSubscription()
时,subscription
参数都为订阅时间父类的订阅者。而event
参数则一直是订阅事件中的唯一参数(最底层子类)。
EventBus#postToSubscription()
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) { switch (subscription.subscriberMethod.threadMode) { case POSTING: invokeSubscriber(subscription, event); break; case MAIN: if (isMainThread) { invokeSubscriber(subscription, event); } else { mainThreadPoster.enqueue(subscription, event); } break; case BACKGROUND: if (isMainThread) { backgroundPoster.enqueue(subscription, event); } else { invokeSubscriber(subscription, event); } break; case ASYNC: asyncPoster.enqueue(subscription, event); break; default: throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode); }}
看到这里差不多可以松口气,终于要分发调用订阅者的订阅事件了!写了整整一下午,容我抽支烟再。
首先根据ThreadMode
确定分发类型。这里以最常用的Main
为例,其余两个Poster
同理。如果是isMainThread=true
,那么直接调用invokeSubscriber()
,否则调用mainThreadPoster.enqueue()
。下面分别解释这两种情况。
EventBus#invokeSubscriber()
void invokeSubscriber(Subscription subscription, Object event) { try { // 反射调用 subscription.subscriberMethod.method.invoke(subscription.subscriber, event); } catch (InvocationTargetException e) { handleSubscriberException(subscription, event, e.getCause()); } catch (IllegalAccessException e) { throw new IllegalStateException("Unexpected exception", e); }}
没撒好说的,直接反射调用订阅者的订阅事件。注意:参数event
是子类对象,就算调用订阅事件中唯一参数是参数的父类,那么传递的仍然是子类对象。笔者已经验证,感兴趣的同学可以自行验证。然后查看HandlerPoster#enqueue()
。
HandlerPoster#enqueue()
final class HandlerPoster extends Handler { ... void enqueue(Subscription subscription, Object event) { // 尝试从pendingPostPool中获取pendingPost,没有则直接new PendingPost PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); synchronized (this) { // 加入队列 queue.enqueue(pendingPost); if (!handlerActive) { handlerActive = true; // 发送空消息 调用handleMessage if (!sendMessage(obtainMessage())) { throw new EventBusException("Could not send handler message"); } } } } @Override public void handleMessage(Message msg) { // 已经切换到主线程 while (true) { // 遍历获取queue中的PendingPost对象 PendingPost pendingPost = queue.poll(); ... // 调用eventBus.invokeSubscriber eventBus.invokeSubscriber(pendingPost); ... } }}
EventBus#invokeSubscriber()
void invokeSubscriber(PendingPost pendingPost) { // 提取订阅事件 Object event = pendingPost.event; // 提取订阅者 Subscription subscription = pendingPost.subscription; // 释放pendingPost PendingPost.releasePendingPost(pendingPost); if (subscription.active) { // 反射调用订阅者的订阅事件 invokeSubscriber(subscription, event); }}
至此,订阅者在相应线程调用订阅事件完成,EventBus.getDefault().Post()
流程完毕。
EventBus#Post()
也只做了三件事
1. 根据订阅事件在subscriptionsByEventType
中查找相应的订阅者
2. 分发订阅者的订阅事件调用线程
2. 通过反射调用订阅者的订阅事件
3. unregister
流程
EventBus#getDefault()
获取EventBus实例
。和Register
流程中一样,不再赘述。
EventBus#unregister()
public synchronized void unregister(Object subscriber) { List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber); if (subscribedTypes != null) { for (Class<?> eventType : subscribedTypes) { unsubscribeByEventType(subscriber, eventType); } typesBySubscriber.remove(subscriber); } else { Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass()); }}
EventBus#unsubscribeByEventType()
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) { List<Subscription> subscriptions = subscriptionsByEventType.get(eventType); if (subscriptions != null) { int size = subscriptions.size(); for (int i = 0; i < size; i++) { Subscription subscription = subscriptions.get(i); if (subscription.subscriber == subscriber) { subscription.active = false; subscriptions.remove(i); i--; size--; } } }}
在EventBus#register()
最后总结道:
将订阅事件作为key
,所有订阅了此订阅事件的订阅者作为value
存放进subscriptionsByEventType
。
将订阅者作为key
,订阅者的所有订阅事件作为value
存放进typesBySubscriber
。
现在要反注册咯。移除相应的key
、value
即可。EventBus3.0
的使用及源码解析到此结束,Have a nice day~
- Android EventBus3.0使用及源码解析
- EventBus3.0使用及源码解析
- Android中EventBus3.0 源码解析
- EventBus3.0 源码解析
- EventBus3.0源码解析
- EventBus3.0源码解析
- EventBus3.0源码解析
- EventBus3.0源码解析
- EventBus3.0源码解析
- Eventbus3.0 源码解析
- EventBus3.0源码解析
- EventBus3.0源码解析
- EventBus3.0源码解析
- EventBus3.0源码解析
- Android事件总线(二)EventBus3.0源码解析
- Android事件总线(二)EventBus3.0源码解析
- EventBus3.0配置及使用
- EventBus3.0原理及使用
- JAVA学习随笔(3)-一些基本概念
- iOS中字体的使用
- Docker for Windows初步体验
- cocos 项目棋魂
- mybatis 面试题
- Android EventBus3.0使用及源码解析
- Docker Swarm集群实践——管理篇
- 二分图(未完。。)
- 计算几何与图形学有关的几种常用算法
- Cortex-M3启动代码分析
- Java 关键字与标识符的概述
- LeetCode - 2. Add Two Numbers
- JavaScript 事件
- 科幻电影中的科技