在SystemUI中,事件的分发处理时通过一个叫做EventBus的类来处理的,那这个类到底是个什么鬼呢?
public class EventBus extends BroadcastReceiver
看到这就明白了,就是一个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的方法是否有效,把有效的方法添加到注册列表
public final void onBusEvent(final Event event) {
这种是有效方法。
4.根据注册的优先级,对注册类进行排序。
到这里注册流程就结束了,下面再来看看事件的分发和处理。
事件的处理是在注册类中重构方法
public final void onBusEvent
来实现的,也就是说,只要发出对应的event,注册类的这个方法就会执行,具体是怎么分发到这个方法的呢?
首先需要发送一个event事件,具体发送如下:
EventBus.getDefault().send(new PackagesChangedEvent(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.注册的时候,我只需要注册类即可,方法是否注册其实不重要,因为反射找不到方法时,我只需要捕获异常即可,何必在注册时多此一举。
后续的需要实验验证后才能知晓。
分享到:
相关推荐
Event Bus是一个发布 /...基于事件总线管理/订阅/分发模式的。事件响应有更多的线程选择, EventBus可以向不同的线程中发布事件。EventBus支持 Sticky Event。 使用时需要先注册订阅,然后向订阅者分发消息数据即可。
别人那看来的,一个事件总线设计的初级demo,方便大家对事件总线进行理解
.NET版本EventBus事件总线实例源码
C#版本EventBus事件总线实例源码
C#版本EventBus事件总线实例源码_(0610).rar.rar
EventBus普通事件和粘性事件
简单EventBus事件总线源码(.net)适合初学者.rar
C#版本EventBus事件总线实例源码2019
C#版本EventBus事件总线实例源码
本项目是Android快速开发... 预想集成工具包,采用MVP开发模式,EventBus数据分发,沉浸式状态栏,ORM,网络请求(HTTPClint,Volley,OkHttps),数据解析,依赖注入(AndroidAnnotations),xutils,图片异步加载,二维码扫描等等,
C#版本EventBus事件总线实例源码-2ZV.rar C#版本EventBus事件总线实例源码-2ZV.rar
简单的时间处理,类似于EventBus的轻量级事件分发器,轻松处理fragment之间的数据互调,activity与service数据的互调,非常方便,同时非常简单,不需要学习EventBus复杂的逻辑,对于轻量级的使用足够了
C#版本EventBus事件总线实例源码(经典)
C#版本EventBus事件总线实例源码.rar.rar
C#版本EventBus事件总线实例源码【201903】