这里我想记录下 eventbus3.0的使用 以及工作原理
首先 我们导入eventbus3.0的依赖:
在gradle中 写入
compile 'org.greenrobot:eventbus:3.0.0'
在代码中注册:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EventBus.getDefault().register(this);//注册EventBus registerReceiver(receiver, getFilter()); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); initView(); setDatabase(); }
在销毁时反注册:
@Override protected void onDestroy() { unregisterReceiver(receiver); super.onDestroy(); EventBus.getDefault().unregister(this); }
在代码中发送消息:
EventBus.getDefault().post(new MyEvent("ssss"));这里 需要自己写一个Event的类 这个类主要用于传递一些你想传递的简易信息
public class MyEvent { public String msg; public MyEvent(String msg) { this.msg = msg; } }
接下来是接收消息这个很关键:
@Subscribe(threadMode = ThreadMode.POSTING) public void onEventMainThread(MyEvent event) { Toast.makeText(MainActivity.this,event.msg+"ads",Toast.LENGTH_LONG).show(); }其中
@Subscribe(threadMode = ThreadMode.POSTING)这里的ThresdMode有四种方式 我们翻开看一下
public enum ThreadMode { /** * Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery * implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for * simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread. */ POSTING, /** * Subscriber will be called in Android's main thread (sometimes referred to as UI thread). If the posting thread is * the main thread, event handler methods will be called directly. Event handlers using this mode must return * quickly to avoid blocking the main thread. */ MAIN, /** * Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single * background thread, that will deliver all its events sequentially. Event handlers using this mode should try to * return quickly to avoid blocking the background thread. */ BACKGROUND, /** * Event handler methods are called in a separate thread. This is always independent from the posting thread and the * main thread. Posting events never wait for event handler methods using this mode. Event handler methods should * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number * of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus * uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications. */ ASYNC }其中的意思是:
MAIN UI主线程
BACKGROUND 后台线程
POSTING 和发布者处在同一个线程
ASYNC 异步线程
所以当我们选择的接收模式不同时 就关系到我们能不能接收到post事件。
接下来我们来看看EventBus3.0 的源码 等我们看完源码之后 我们会对EventBus有个新的认知
首先我们从EventBus.getDefault().register(this)入手,
EventBus.getDefault()里面:
/** Convenience singleton for apps using a process-wide EventBus instance. */ public static EventBus getDefault() { if (defaultInstance == null) { synchronized (EventBus.class) { if (defaultInstance == null) { defaultInstance = new EventBus(); } } } return defaultInstance; }从代码可以看出 EventBus是单例模式的 这样也有助于消息的管理
我们再看register:
/** * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they * are no longer interested in receiving events. * * Subscribers have event handling methods that must be annotated by {@link Subscribe}. * The {@link Subscribe} annotation also allows configuration like {@link * ThreadMode} and priority. */ public void register(Object subscriber) { Class> subscriberClass = subscriber.getClass(); List从这段代码我们可以看出首先获取订阅者的类对象Class> subscriberClass = subscriber.getClass();subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } } }
在下面那句代码中 用到了这个对象
我们发现下面有个SubscriberMethod的集合 还有个叫subscriberMethodFinder的类
那么这些东西究竟是干什么的呢
我们继续探寻
public class SubscriberMethod { final Method method; final ThreadMode threadMode; final Class> eventType; final int priority; final boolean sticky; /** Used for efficient comparison */ String methodString; public SubscriberMethod(Method method, Class> eventType, ThreadMode threadMode, int priority, boolean sticky) { this.method = method; this.threadMode = threadMode; this.eventType = eventType; this.priority = priority; this.sticky = sticky; }从SubscriberMethod 我们可以看到 这是一个保存方法 线程模式 等等的类 那我们看看后面那个subscriberMethodFinder调用的方法 先逐个击破:
ListfindSubscriberMethods(Class> subscriberClass) { List subscriberMethods = METHOD_CACHE.get(subscriberClass); if (subscriberMethods != null) { return subscriberMethods; } 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; } }
private static final Map我们可以看到 首先是从缓存中读取 如果没有 就走到下面, List > METHOD_CACHE = new ConcurrentHashMap<>();
if (ignoreGeneratedIndex) { subscriberMethods = findUsingReflection(subscriberClass); } else { subscriberMethods = findUsingInfo(subscriberClass); }这里是说是否忽略注解器生成的MyEventBusIndex类 如果忽略就从反射拿去 如果不忽略 就直接从注解器拿取
拿到之后就保存进缓存
那我们看看这两个方法
我们先来看通过反射的方法
private List一个一个了解过去我们发现 FindState只用于储存一些信息 getMethodsAndRelease只是把FindState里面的SubscriberMethod集合返回 那么 关键就在于findUsingReflection(Class> subscriberClass) { FindState findState = prepareFindState(); findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { findUsingReflectionInSingleClass(findState); findState.moveToSuperclass(); } return getMethodsAndRelease(findState); }
findUsingReflectionInSingleClass(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; } 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"); } } }走完这里 我们发现只要类中带有Subscribe注解标签的方法都会被构建成一个SubscribeMethod保存到findstate
最后在
getMethodsAndRelease(findState)
中将集合返回给上一层
那findUsingInfo(subscriberClass);又如何走的呢:
private List从代码一步一步看下来findUsingInfo(Class> subscriberClass) { FindState findState = prepareFindState(); findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { findState.subscriberInfo = getSubscriberInfo(findState); 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.moveToSuperclass(); } return getMethodsAndRelease(findState); }
void initForSubscriber(Class> subscriberClass) { this.subscriberClass = clazz = subscriberClass; skipSuperClasses = false; subscriberInfo = null; }
我们很容易发现 findState.subscriberInfo 将会默认为空 然后会走到
findUsingReflectionInSingleClass(findState);
这个方法 那么又和上面一样了 就这样 我们注册的时候得到了所有标有Subscribe 方法的集合
接着我们接着回到注册来看:
synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } }然后遍历执行subscribe()方法。看样子应该是遍历List
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { // 获取订阅事件的类型,即订阅方法中的唯一参数类型 Class> eventType = subscriberMethod.eventType; // 用订阅者和订阅方法构造一个Subscription对象 Subscription newSubscription = new Subscription(subscriber, subscriberMethod); // 查找所有的订阅了订阅事件的订阅者 CopyOnWriteArrayListRegister()其实只做了三件事:subscriptions = subscriptionsByEventType.get(eventType); // 没有订阅者订阅过则新建个CopyOnWriteArrayList ,并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 > 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 ). Set, Object>> entries = stickyEvents.entrySet(); for (Map.Entry , 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); } } }
接下来Post():
public void post(Object event) { // 依据不同的线程获取相应的刚初始化的PostingThreadState PostingThreadState postingState = currentPostingThreadState.get(); List接着进入postSingleEvent:
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { // 获取event的类型 Class> eventClass = event.getClass(); boolean subscriptionFound = false; // eventInheritance默认为true if (eventInheritance) { // 依据订阅事件类型,将订阅事件类型及所有父类添加进eventTypes。详情见下文lookupAllEventTypes()分析 List> 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)); } } }
private static List> lookupAllEventTypes(Class> eventClass) { synchronized (eventTypesCache) { // 根据订阅事件查找所有自身及父类,eventTypes默认为null List > 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; } }
/** Recurses through super interfaces. */ static void addInterfaces(List> eventTypes, Class>[] interfaces) { for (Class> interfaceClass : interfaces) { if (!eventTypes.contains(interfaceClass)) { eventTypes.add(interfaceClass); addInterfaces(eventTypes, interfaceClass.getInterfaces()); } } }
下面看postSingleEventForEventType:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class> eventClass) { CopyOnWriteArrayList注意看这里: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; }
subscriptions = subscriptionsByEventType.get(eventClass);在注册的时候
将订阅事件作为key,所有订阅了此订阅事件的订阅者作为value存放进subscriptionsByEventType
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()
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); } }
void enqueue(Subscription subscription, Object event) { PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); synchronized (this) { queue.enqueue(pendingPost); if (!handlerActive) { handlerActive = true; if (!sendMessage(obtainMessage())) {
//发送消息 throw new EventBusException("Could not send handler message"); } } } }
static PendingPost obtainPendingPost(Subscription subscription, Object event) { synchronized (pendingPostPool) { int size = pendingPostPool.size(); if (size > 0) { PendingPost pendingPost = pendingPostPool.remove(size - 1); pendingPost.event = event; pendingPost.subscription = subscription; pendingPost.next = null; return pendingPost; } } return new PendingPost(event, subscription); }尝试从pendingPostPool中获取pendingPost,没有则直接new PendingPost
@Override public void handleMessage(Message msg) { boolean rescheduled = false; try { long started = SystemClock.uptimeMillis();
// 已经切换到主线程
while (true) {
// 遍历获取queue中的PendingPost对象 PendingPost pendingPost = queue.poll(); if (pendingPost == null) { synchronized (this) { // Check again, this time in synchronized pendingPost = queue.poll(); if (pendingPost == null) { handlerActive = false; return; } } }
// 调用eventBus.invokeSubscriber eventBus.invokeSubscriber(pendingPost); long timeInMethod = SystemClock.uptimeMillis() - started; if (timeInMethod >= maxMillisInsideHandleMessage) { if (!sendMessage(obtainMessage())) { throw new EventBusException("Could not send handler message"); } rescheduled = true; return; } } } finally { handlerActive = rescheduled; } }
void invokeSubscriber(PendingPost pendingPost) { // 提取订阅事件 Object event = pendingPost.event; // 提取订阅者 Subscription subscription = pendingPost.subscription; // 释放pendingPost PendingPost.releasePendingPost(pendingPost); if (subscription.active) { // 反射调用订阅者的订阅事件 invokeSubscriber(subscription, event); } }
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()也只做了三件事
最后:
/** Unregisters the given subscriber from all event classes. */ public synchronized void unregister(Object subscriber) { List> 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()); } }
/** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */ private void unsubscribeByEventType(Object subscriber, Class> eventType) { Listunregister():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--; } } } }
将subscriptionsByEventType,typesBySubscriber的key和value移除清空。
好了 写到这里!