EventBus是什么?
EventBus is a publish/subscribe event bus for Android and Java.
EventBus特性?
1. 发送者 接收者 解耦。发布-订阅模式框架。让多个观察者对象同时监听某一个主题对象。
2. 在活动、片段和后台线程中表现良好。
3. 避免复杂且容易出错的依赖关系和生命周期问题。
4. 让代码更简洁。
5. 快!
6. 小,60K左右。
7. 10亿的安装和使用,非常可靠!经得起考验!
8. 具有交付线程、订阅者优先级等高级功能。
9. 业内对EventBus的主要争论点是在于EventBus使用反射会出现性能问题(invoke()方法调用与直接调用相比有一丢丢性能损耗)。
10. 可以使用注解处理器预处理获取订阅信息(预处理策略),也会将订阅者的方法缓存到METHOD_CACHE里避免重复查找(缓存策略)。
EventBus使用?
1. 定义事件。
public static class MessageEvent { /* Additional fields if needed */ }
2. 声明和注释订阅方法。
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
3. 发送事件。
EventBus.getDefault().post(new MessageEvent());
EventBus源码?
- 下图引用自文章:EventBus 3.0 源码分析(详见Reference链接)
-
获取EventBus对象
-- 双重锁 单例模式 public static EventBus getDefault() { if (defaultInstance == null) { synchronized (EventBus.class) { if (defaultInstance == null) { defaultInstance = new EventBus(); } } } return defaultInstance; }
-
创建EventBus对象
-- EventBusBuilder 将配置解耦出去,使我们的代码结构更清晰。 -- CopyOnWriteArrayList 分身、读写分离,容器修改过程无锁定,修改开始时锁定,保障高效读。缺点是:读的数据有一定延迟。 private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder(); public EventBus() { this(DEFAULT_BUILDER); } EventBus(EventBusBuilder builder) { //key:订阅的事件,value:订阅这个事件的所有订阅者集合 //private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType; subscriptionsByEventType = new HashMap<>(); //key:订阅者对象,value:这个订阅者订阅的事件集合 //private final Map<Object, List<Class<?>>> typesBySubscriber; typesBySubscriber = new HashMap<>(); //粘性事件 key:粘性事件的class对象, value:事件对象 //private final Map<Class<?>, Object> stickyEvents; stickyEvents = new ConcurrentHashMap<>(); //事件主线程处理 mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10); //事件 Background 处理 backgroundPoster = new BackgroundPoster(this); //事件异步线程处理 asyncPoster = new AsyncPoster(this); indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0; //订阅者响应函数信息存储和查找类 subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes, builder.strictMethodVerification, builder.ignoreGeneratedIndex); logSubscriberExceptions = builder.logSubscriberExceptions; logNoSubscriberMessages = builder.logNoSubscriberMessages; sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent; sendNoSubscriberEvent = builder.sendNoSubscriberEvent; throwSubscriberException = builder.throwSubscriberException; //是否支持事件继承 eventInheritance = builder.eventInheritance; executorService = builder.executorService; }
-
借助EventBus订阅者进行注册
public void register(Object subscriber) { //首先获得订阅者的class对象 Class<?> subscriberClass = subscriber.getClass(); //通过subscriberMethodFinder来找到订阅者订阅了哪些事件.返回一个SubscriberMethod对象的List,SubscriberMethod //里包含了这个方法的Method对象,以及将来响应订阅是在哪个线程的ThreadMode,以及订阅的事件类型eventType,以及订阅的优 //先级priority,以及是否接收粘性sticky事件的boolean值. List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { //订阅 subscribe(subscriber, subscriberMethod); } } } List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) { //先从METHOD_CACHE取看是否有缓存,key:保存订阅类的类名,value:保存类中订阅的方法数据, List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass); if (subscriberMethods != null) { return subscriberMethods; } //是否忽略注解器生成的MyEventBusIndex类 if (ignoreGeneratedIndex) { //利用反射来读取订阅类中的订阅方法信息 subscriberMethods = findUsingReflection(subscriberClass); } else { //从注解器生成的MyEventBusIndex类中获得订阅类的订阅方法信息 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缓存 METHOD_CACHE.put(subscriberClass, subscriberMethods); return subscriberMethods; } } private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) { //FindState 用来做订阅方法的校验和保存 FindState findState = prepareFindState(); findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { //通过反射来获得订阅方法信息 findUsingReflectionInSingleClass(findState); //查找父类的订阅方法 findState.moveToSuperclass(); } //获取findState中的SubscriberMethod(也就是订阅方法List)并返回 return getMethodsAndRelease(findState); } 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; } //遍历Method for (Method method : methods) { int modifiers = method.getModifiers(); if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { Class<?>[] parameterTypes = method.getParameterTypes(); //保证必须只有一个事件参数 if (parameterTypes.length == 1) { //得到注解 Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); if (subscribeAnnotation != null) { Class<?> eventType = parameterTypes[0]; //校验是否添加该方法 if (findState.checkAdd(method, eventType)) { ThreadMode threadMode = subscribeAnnotation.threadMode(); //实例化SubscriberMethod对象并添加 findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(), subscribeAnnotation.sticky())); } } } 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"); } } }
-
@Subscribe 注解实现
-- @Subscribe():在3.0版本中,EventBus提供了一个EventBusAnnotationProcessor注解处理器来在编译期通过读取@Subscribe()注解并解析,处理其中所包含的信息,然后生成java类来保存所有订阅者关于订阅的信息,这样就比在运行时使用反射来获得这些订阅者的信息速度要快。 /** * This class is generated by EventBus, do not edit. */ public class MyEventBusIndex implements SubscriberInfoIndex { private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX; static { SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>(); putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscriberClassEventBusAsync.class, true, new SubscriberMethodInfo[]{ new SubscriberMethodInfo("onEventAsync", TestEvent.class, ThreadMode.ASYNC), })); putIndex(new SimpleSubscriberInfo(TestRunnerActivity.class, true, new SubscriberMethodInfo[]{ new SubscriberMethodInfo("onEventMainThread", TestFinishedEvent.class, ThreadMode.MAIN), })); } private static void putIndex(SubscriberInfo info) { SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info); } @Override public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) { SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass); if (info != null) { return info; } else { return null; } } } //必须在同步代码块里调用 private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { //获取订阅的事件类型 Class<?> eventType = subscriberMethod.eventType; //创建Subscription对象 Subscription newSubscription = new Subscription(subscriber, subscriberMethod); //从subscriptionsByEventType里检查是否已经添加过该Subscription,如果添加过就抛出异常 CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList<>(); subscriptionsByEventType.put(eventType, subscriptions); } else { if (subscriptions.contains(newSubscription)) { throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType); } } //根据优先级priority来添加Subscription对象 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里 List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber); if (subscribedEvents == null) { subscribedEvents = new ArrayList<>(); typesBySubscriber.put(subscriber, subscribedEvents); } subscribedEvents.add(eventType); //如果接收sticky事件,立即分发sticky事件 if (subscriberMethod.sticky) { //eventInheritance 表示是否分发订阅了响应事件类父类事件的方法 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()
过程:下图引用自文章:EventBus 3.0 源码分析(详见Reference链接) -
事件分发,EventBus.getDefault().post(“str”);
public void post(Object event) { //得到当前线程的Posting状态. PostingThreadState postingState = currentPostingThreadState.get(); //获取当前线程的事件队列 List<Object> eventQueue = postingState.eventQueue; eventQueue.add(event); 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 { //一直发送 while (!eventQueue.isEmpty()) { //发送单个事件 postSingleEvent(eventQueue.remove(0), postingState); } } finally { postingState.isPosting = false; postingState.isMainThread = false; } } } private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() { @Override protected PostingThreadState initialValue() { return new PostingThreadState(); } }; private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { Class<?> eventClass = event.getClass(); boolean subscriptionFound = false; //是否触发订阅了该事件(eventClass)的父类,以及接口的类的响应方法. if (eventInheritance) { //查找eventClass类所有的父类以及接口 List<Class<?>> eventTypes = lookupAllEventTypes(eventClass); int countTypes = eventTypes.size(); //循环postSingleEventForEventType for (int h = 0; h < countTypes; h++) { Class<?> clazz = eventTypes.get(h); //只要右边有一个为true,subscriptionFound就为true subscriptionFound |= postSingleEventForEventType(event, postingState, clazz); } } else { //post单个 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) { //发送一个NoSubscriberEvent事件,如果我们需要处理这种状态,接收这个事件就可以了 post(new NoSubscriberEvent(this, event)); } } } private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) { CopyOnWriteArrayList<Subscription> subscriptions; //获取订阅了这个事件的Subscription列表. 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 { //分发给订阅者 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; } 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); } } 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); } }
-
Post流程:下图引用自文章:EventBus 3.0 源码分析(详见Reference链接)
-
解除注册:
public synchronized void unregister(Object subscriber) { //通过typesBySubscriber来取出这个subscriber订阅者订阅的事件类型, List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber); if (subscribedTypes != null) { //分别解除每个订阅了的事件类型 for (Class<?> eventType : subscribedTypes) { unsubscribeByEventType(subscriber, eventType); } //从typesBySubscriber移除subscriber typesBySubscriber.remove(subscriber); } else { Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass()); } } private void unsubscribeByEventType(Object subscriber, Class<?> eventType) { //subscriptionsByEventType里拿出这个事件类型的订阅者列表. 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--; } } } }
-
关系梳理:
订阅者订阅的事件类型 List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber); 编译期通过读取@Subscribe 注解解析过程中保存构建的关系。 注册过程其实是:订阅者 即一个类,将自己的元信息 即 哪些方法订阅了哪些事件 的关系 进行存储。后续 可以通过事件类型 找到 订阅者列表,订阅者列表中 每个订阅者 可以通过类 找到 方法信息,以及 方法订阅的事件类型。 //从subscriptionsByEventType里检查是否已经添加过该Subscription,如果添加过就抛出异常 CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); 没有则按照优先级进行添加。 post过程其实是:事件 到 通过事件类型找订阅者列表 反射调用。 //得到当前线程的Posting状态. PostingThreadState postingState = currentPostingThreadState.get(); //获取当前线程的事件队列 List<Object> eventQueue = postingState.eventQueue; eventQueue.add(event); 事件类型的订阅者列表 List<Subscription> subscriptions = subscriptionsByEventType.get(eventType); postToSubscription(Subscription subscription, Object event, boolean isMainThread); 其中有缓存策略的应用、builder对配置信息的装载,详见类图。
Reference
- https://github.com/greenrobot/EventBus(github)
- https://www.jianshu.com/p/f057c460c77e(EventBus 3.0 源码分析)
- https://kymjs.com/code/2015/12/16/01/(EventBus源码研读(下))