EventBus事件分发处理分析
在SystemUI中,事件的分发处理时通过一个叫做EventBus的类来处理的,那这个类到底是个什么鬼呢?
publicclassEventBusextendsBroadcastReceiver
看到这就明白了,就是一个receiver啊,那就简单了,这个类就是一个管理所有intent,然后统一注册,统一分发的一个中间件。既然时receiver,那肯定有register注册的方法吧,继续跟踪,果然发现了注册的地方
private void registerReceiverForInterprocessEvents(Context context) { android.util.Log.e("XXX","registerReceiverForInterprocessEvents"); if (DEBUG_TRACE_ALL) { logWithPid("registerReceiverForInterprocessEvents()"); } // Rebuild the receiver filter with the new interprocess events IntentFilter filter = new IntentFilter(); for (String eventName : mInterprocessEventNameMap.keySet()) { android.util.Log.e("XXX","registerReceiverForInterprocessEvents "+eventName); filter.addAction(eventName); if (DEBUG_TRACE_ALL) { logWithPid(" filter: " + eventName); } } // Re-register the receiver with the new filter if (mHasRegisteredReceiver) { context.unregisterReceiver(this); } context.registerReceiverAsUser(this, UserHandle.ALL, filter, PERMISSION_SELF, mHandler); mHasRegisteredReceiver = true; }
那就继续找,看这个方法在哪使用,最终找到了使用的地方
public void registerInterprocessAsCurrentUser(Context context, Object subscriber) { registerInterprocessAsCurrentUser(context, subscriber, DEFAULT_SUBSCRIBER_PRIORITY); }
遗憾的是这个方法压根就没有地方调用,吓人呢,没有地方调用,那这就相当于没注册啊,那搞这么一堆代码,是闲的吗?这条线是走不下去了。既然不没有注册,那它的onReceiver方法是不是也就不执行呢?
@Override public void onReceive(Context context, Intent intent) { android.util.Log.e("XXX","onReceive "); if (DEBUG_TRACE_ALL) { logWithPid("onReceive(" + intent.getAction() + ", user " + UserHandle.myUserId() + ")"); } Bundle eventBundle = intent.getBundleExtra(EXTRA_INTERPROCESS_EVENT_BUNDLE); Class<? extends InterprocessEvent> eventType = mInterprocessEventNameMap.get(intent.getAction()); try { Constructor<? extends InterprocessEvent> ctor = eventType.getConstructor(Bundle.class); send((Event) ctor.newInstance(eventBundle)); } catch (NoSuchMethodException| InvocationTargetException| InstantiationException| IllegalAccessException e) { Log.e(TAG, "Failed to create InterprocessEvent", e.getCause()); } }
我们打log看看,结果真没有执行,那这个继承receiver就比较扯淡了,继承了不用,那这个事件到底是怎么分发的呢?
Receiver这条路走不通,我们就直接从EventBus的使用开始查找。
使用EventBus首先必须注册,通过方法
EventBus.getDefault().register(this,EVENT_BUS_PRIORITY);
其中EventBus.getDefault()就是获取一个EventBus对象,这个方法是同步的单例模式。this参数就是一个Object对象,第二个参数时优先级
register都干了什么呢?它的主要实现方法如下
private void registerSubscriber(Object subscriber, int priority, MutableBoolean hasInterprocessEventsChangedOut) { android.util.Log.e("XXX","registerSubscriber "+subscriber); // Fail immediately if we are being called from the non-main thread long callingThreadId = Thread.currentThread().getId(); if (callingThreadId != mHandler.getLooper().getThread().getId()) { throw new RuntimeException("Can not register() a subscriber from a non-main thread."); } // Return immediately if this exact subscriber is already registered if (findRegisteredSubscriber(subscriber, false /* removeFoundSubscriber */)) { return; } long t1 = 0; if (DEBUG_TRACE_ALL) { t1 = SystemClock.currentTimeMicro(); logWithPid("registerSubscriber(" + subscriber.getClass().getSimpleName() + ")"); } Subscriber sub = new Subscriber(subscriber, SystemClock.uptimeMillis()); Class<?> subscriberType = subscriber.getClass(); ArrayList<EventHandlerMethod> subscriberMethods = mSubscriberTypeMap.get(subscriberType); if (subscriberMethods != null) { if (DEBUG_TRACE_ALL) { logWithPid("Subscriber class type already registered"); } // If we've parsed this subscriber type before, just add to the set for all the known // events for (EventHandlerMethod method : subscriberMethods) { ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(method.eventType); eventTypeHandlers.add(new EventHandler(sub, method, priority)); sortEventHandlersByPriority(eventTypeHandlers); } mSubscribers.add(sub); return; } else { if (DEBUG_TRACE_ALL) { logWithPid("Subscriber class type requires registration"); } // If we are parsing this type from scratch, ensure we add it to the subscriber type // map, and pull out he handler methods below subscriberMethods = new ArrayList<>(); mSubscriberTypeMap.put(subscriberType, subscriberMethods); mSubscribers.add(sub); } // Find all the valid event bus handler methods of the subscriber MutableBoolean isInterprocessEvent = new MutableBoolean(false); Method[] methods = subscriberType.getDeclaredMethods(); for (Method m : methods) { Class<?>[] parameterTypes = m.getParameterTypes(); isInterprocessEvent.value = false; if (isValidEventBusHandlerMethod(m, parameterTypes, isInterprocessEvent)) { Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0]; ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(eventType); if (eventTypeHandlers == null) { eventTypeHandlers = new ArrayList<>(); mEventTypeMap.put(eventType, eventTypeHandlers); } if (isInterprocessEvent.value) { try { // Enforce that the event must have a Bundle constructor eventType.getConstructor(Bundle.class); mInterprocessEventNameMap.put(eventType.getName(), (Class<? extends InterprocessEvent>) eventType); if (hasInterprocessEventsChangedOut != null) { hasInterprocessEventsChangedOut.value = true; } } catch (NoSuchMethodException e) { throw new RuntimeException("Expected InterprocessEvent to have a Bundle constructor"); } } EventHandlerMethod method = new EventHandlerMethod(m, eventType); EventHandler handler = new EventHandler(sub, method, priority); eventTypeHandlers.add(handler); subscriberMethods.add(method); sortEventHandlersByPriority(eventTypeHandlers); if (DEBUG_TRACE_ALL) { logWithPid(" * Method: " + m.getName() + " event: " + parameterTypes[0].getSimpleName() + " interprocess? " + isInterprocessEvent.value); } } } if (DEBUG_TRACE_ALL) { logWithPid("Registered " + subscriber.getClass().getSimpleName() + " in " + (SystemClock.currentTimeMicro() - t1) + " microseconds"); } }
这个方法代码比较多,大致就分为以下步骤:
注册的类标记为A
1.判断类A是否已经注册过,如果注册过,就返回,否则继续下一步。主要判断变量
2.判断类A中的方法是否注册过,如果注册过,则注册完成类A后,直接返回,否则继续注册
3.判断类A的方法是否有效,把有效的方法添加到注册列表
publicfinalvoidonBusEvent(finalEventevent){
这种是有效方法。
4.根据注册的优先级,对注册类进行排序。
到这里注册流程就结束了,下面再来看看事件的分发和处理。
事件的处理是在注册类中重构方法
publicfinalvoidonBusEvent
来实现的,也就是说,只要发出对应的event,注册类的这个方法就会执行,具体是怎么分发到这个方法的呢?
首先需要发送一个event事件,具体发送如下:
EventBus.getDefault().send(newPackagesChangedEvent(packageName,userId));
其中PackagesChangedEvent就是继承了EventBus的内部类Event。
send方法实现如下:
public void send(Event event) { // Fail immediately if we are being called from the non-main thread long callingThreadId = Thread.currentThread().getId(); if (callingThreadId != mHandler.getLooper().getThread().getId()) { throw new RuntimeException("Can not send() a message from a non-main thread."); } if (DEBUG_TRACE_ALL) { logWithPid("send(" + event.getClass().getSimpleName() + ")"); } // Reset the event's cancelled state event.requiresPost = false; event.cancelled = false; queueEvent(event); }
继续往下跟,发现事件处理分为3部分,处理前,处理中,处理后,其中前和后都是空方法,当然具体的实现已经给出接口,只需要你在定义自己的event时,复写父类的方法即可。处理中的主要实现方法如下:
private void processEvent(final EventHandler eventHandler, final Event event) { android.util.Log.e("XXX","processEvent "+event+" "+eventHandler); // Skip if the event was already cancelled if (event.cancelled) { if (event.trace || DEBUG_TRACE_ALL) { logWithPid("Event dispatch cancelled"); } return; } try { if (event.trace || DEBUG_TRACE_ALL) { logWithPid(" -> " + eventHandler.toString()); } Object sub = eventHandler.subscriber.getReference(); if (sub != null) { long t1 = 0; if (DEBUG_TRACE_ALL) { t1 = SystemClock.currentTimeMicro(); } eventHandler.method.invoke(sub, event); if (DEBUG_TRACE_ALL) { long duration = (SystemClock.currentTimeMicro() - t1); mCallDurationMicros += duration; mCallCount++; logWithPid(eventHandler.method.toString() + " duration: " + duration + " microseconds, avg: " + (mCallDurationMicros / mCallCount)); } } else { Log.e(TAG, "Failed to deliver event to null subscriber"); } } catch (IllegalAccessException e) { Log.e(TAG, "Failed to invoke method", e.getCause()); } catch (InvocationTargetException e) { throw new RuntimeException(e.getCause()); } }
到这就结束了,看到了最后的调用是通过遍历所有注册过Busevent的类,然后通过反射,找到具体的方法,进行执行。
到这就哟问题了:
1.EventBus继承receiver到底有没有必要,因为我虽然继承了它,但是没有使用。
2.注册的时候,我只需要注册类即可,方法是否注册其实不重要,因为反射找不到方法时,我只需要捕获异常即可,何必在注册时多此一举。
后续的需要实验验证后才能知晓。