`
zhy20045923
  • 浏览: 153624 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

EventBus事件分发处理分析

 
阅读更多
在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.注册的时候,我只需要注册类即可,方法是否注册其实不重要,因为反射找不到方法时,我只需要捕获异常即可,何必在注册时多此一举。

后续的需要实验验证后才能知晓。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics