`
zhy20045923
  • 浏览: 157001 次
  • 性别: 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.注册的时候,我只需要注册类即可,方法是否注册其实不重要,因为反射找不到方法时,我只需要捕获异常即可,何必在注册时多此一举。

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

相关推荐

    .NET版本EventBus事件总线实例源码

    .NET版本的EventBus是一种设计模式实现,用于在应用程序的不同组件之间传递消息,它基于发布/订阅原则,使得组件之间可以松耦合地通信。...对于进一步的学习,你可以分析源码,了解它如何处理事件的发布、订阅和分发。

    C#版本EventBus事件总线实例源码2019

    【C#版本EventBus事件总线实例源码2019】是一个关于C#编程语言中的事件总线设计模式的应用示例。...通过阅读和分析这个源码,你可以深入理解C#中的事件处理和事件总线,并将其应用到自己的项目中。

    C#版本EventBus事件总线实例源码

    EventBus是一种全局单例模式的应用,用于在整个应用程序中分发和接收事件。它提供了统一的接口,使得各个组件之间可以通过发布和订阅事件来交互,而不是直接引用对方。 3. **实现EventBus** - 定义一个公共类,...

    EventBus 原理简化分析版

    7. **事件分发(Event Delivery)**:EventBus 使用了观察者模式,当一个事件被发布时,它会遍历所有已注册的订阅者并根据线程模型和优先级来分发事件。 8. **异常处理(Exception Handling)**:如果在事件处理...

    C#版本EventBus事件总线实例源码__0525).rar

    8. **事件分发策略**:EventBus可能有不同的事件分发策略,比如同步分发(所有订阅者依次处理事件)、异步分发(并发处理事件)或者根据优先级分发。 9. **测试与日志**:良好的EventBus实现应考虑单元测试和日志...

    C#版本EventBus事件总线实例源码.rar

    `C#版本EventBus事件总线实例源码.rar`提供的内容可能包括一个实现事件总线概念的C#库,以及一些示例代码,用于演示如何在实际项目中使用这个库。 事件总线的核心思想是发布/订阅(Publish-Subscribe)模型。在这个...

    C#版本EventBus事件总线实例源码_(0601).rar

    下面我们将深入探讨C#版本的EventBus事件总线实例,并分析其源码。 首先,让我们理解事件总线的基本概念。事件总线是应用中的一个中心组件,它接收并分发事件。事件可以看作是对象之间通信的一种方式,它们通常包含...

    C#版本EventBus事件总线实例源码__0525.rar

    通过分析这个C#版本的EventBus事件总线实例源码,开发者可以学习到如何在C#中实现一个简单的事件总线系统,以及如何在项目中应用事件驱动的设计思想。这不仅加深了对C#事件机制的理解,也为构建复杂、可扩展的应用...

    C#版本EventBus事件总线实例源码-9s.rar

    3. **事件总线(Event Bus)**:作为中间人,负责维护事件发布者和订阅者之间的关系,以及触发事件的分发。 在C#中实现事件总线,我们可以创建一个静态类,如`EventBus`,提供`Publish`方法用于发布事件,以及`...

    Node.js-EventBus安卓优化的事件总线

    7. **性能优化**:GreenRobot EventBus通过优化如内存管理和多线程处理来提供高效的事件分发。 8. **事件类型**:EventBus允许定义多种事件类,通过类名或自定义注解区分不同的事件。 9. **订阅者方法注解**:在...

    C#版本EventBus事件总线实例源码(0520_).rar

    4. **发布/订阅逻辑**:EventBus类需要实现将事件分发给所有订阅了该事件的处理器。这可能涉及到线程安全问题,因此可能使用了锁或者其他并发控制机制。 5. **应用示例**:源码可能包含一些测试或示例代码,展示了...

    eventBus 3.0 带有注释的源码

    8. **事件分发(Event Delivery)**: - EventBus 使用二叉树结构存储订阅者,根据事件类型快速找到订阅者。事件发布时,EventBus 会遍历树并调用相应的订阅者方法。 9. **调试支持(Debugging Support)**: - ...

    EventBus源码及demo

    通过分析 "EventBus" 源码,我们可以更深入地理解其内部的工作机制,如事件的分发、线程调度、订阅者管理等。这有助于我们优化性能、调试问题,并更好地集成到自己的项目中。总的来说,EventBus 是 Android 开发中...

    EventBus学习源码

    2. **事件分发**:当调用 `EventBus.getDefault().post(event)` 发布事件时,EventBus 遍历所有的订阅者,根据事件类型匹配合适的订阅方法,并通过反射调用这些方法。 EventBus 还支持注解参数,如 `@ThreadMode`,...

    EventBus使用教程Demo

    EventBus 的设计灵感来源于 Publish/Subscribe 模式,它通过发布(Publish)事件到事件总线(Event Bus),然后由订阅者(Subscriber)监听并处理这些事件。EventBus 提供了无须创建意图(Intent)、接口或回调的...

    EventBus的DEMO.zip

    - **线程模式(Thread Mode)**: EventBus 提供了四种线程模式,控制事件的分发是在主线程、后台线程还是自定义线程中执行。 - **MAIN**: 在主线程中执行,适合更新 UI。 - **ASYNC**: 在后台线程中执行,适合...

    eventbus-2.1.0-beta-1.jar

    3. **事件分发**:EventBus 使用反射机制在运行时动态发现订阅者的方法,根据事件类型和线程模式进行事件的分发。它使用一个线程安全的队列来缓存事件,保证了事件的顺序和并发控制。 4. **异常处理**:当订阅者...

    Android框架EventBus实例

    EventBus维护了一个事件队列,当有新的事件发布时,它会将事件分发给所有订阅了该事件的订阅者。 **安装与配置** 在项目中集成EventBus,首先需要在build.gradle文件中添加依赖: ```groovy dependencies { ...

    EventBus3.0 Demo

    1. **事件分发(Delivery)**:EventBus的核心在于事件的分发机制,它使用了`PostingThreadState`来保存当前线程的状态,通过`EventHandler`类进行实际的事件传递。 2. **事件订阅管理(Subscription Storage)**:`...

    安卓Android源码——EventBus-master.zip

    通过对 EventBus 源码的学习,开发者可以深入了解其内部的订阅者管理、事件分发、线程调度等机制,这对于定制化需求或者创建自己的事件系统会有很大帮助。同时,理解 EventBus 的工作原理也有助于优化应用性能,避免...

Global site tag (gtag.js) - Google Analytics