从源码角度学习EventBus

引言: 最近看了EventBus的源码,看完后分享下自己的理解

  • 写法约定: 文件的eventTypeClass 对应事件的Class对象,ObjectClass对应Object类的Class对象
  • EventBus简介:以观察者模式为基本思想,实现消息推送/订阅功能,用于Android组件之间相互通信的开源框架。
1. EventBus类结构分析

EventBus可以说是一个比较简洁的事件订阅框架了,其实EventBus中就可以看到很多的实现代码了,所以EventBus的源码还是挺好理解的,阅读过程围绕几个关键流程展开就好。

//EventBus的映射表
public class EventBus {
   //每一个事件对应的事件集合(如果EventBusBuilder.eventInheritance为true,他会收集当前事件类的所有接口和父类)
   //如果是接口会向集成关系上层递归遍历所有的interface,如果是当前事件的父类则直向上收集一层,如果当前类的父类是Object了,那么ObjectClass也会被加入到List<Class>集合中,下面具体看这些映射表存储的是什么.
   private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
   
   //事件和订阅者方法映射表,可以形成:eventTypeClass->subscriberObject, eventTypeClass, method,
   private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
   
   //<Subscriber, List<eventType>>  subscriber->eventTypeClass*
   private final Map<Object, List<Class<?>>> typesBySubscriber;
   
   //粘性事件Class对象和粘性事件映射表
   private final Map<Class<?>, Object> stickyEvents;
   }

从上面EventBus的结构中就可以看出,EventBus管理事件的方法,就是用建立一些映射表,存储[事件-发送者-订阅者]的关联关系, 这也是观察者模式一种通用的思路,用第三方的集合或者映射表管理事件、发送者和订阅者的关系,可以实现结构上比较松散的耦合

另外,上面这些映射表的命名都很有规律,[aaa]sBy[bbb],那么aaa就是map中的value, bbb就是key,这种命名方式在日常开发中可以借鉴的。


2. 注册流程分析
  • 2.1 注册:EventBus#register()
    EventBus#register()的实现:
public void register(Object subscriber) {
		//(1)使用注册时传入的Object,其实是想拿Class对象,有了一个对象的Class对象可以说就掌握某个interface,class的所有内容
        Class<?> subscriberClass = subscriber.getClass();
        //(2)使用订阅者Class对象查找进行订阅了的Method
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
        //(3)遍历注册时传入的订阅者的所有订阅方法,并将订阅者和订阅方法建立订阅关系
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
         }
        }
    }
  • SubscriberMethod数据结构
 //从结构中可以看到其中封装了订阅者的Method,eventType等信息
 public class SubscriberMethod {
    final Method method; //进行注册的订阅者Class对象或者到的Method对象
    final ThreadMode threadMode; 
    final Class<?> eventType; //发送-接收过程中定义的事件Class对象,后面从源码中验证其含义
    final int priority; //优先级
    final boolean sticky; //是否标记为粘性事件
    /** Used for efficient comparison */
    String methodString; 
    .....
  }
  • Subscription数据结构
/**
 * 将订阅者和订阅方法封装在一起
 */
final class Subscription {
    final Object subscriber;
    final SubscriberMethod subscriberMethod;
    /**
     * Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
     * {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
     */
    volatile boolean active;

    Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
        this.subscriber = subscriber;
        this.subscriberMethod = subscriberMethod;
        active = true;
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Subscription) {
            Subscription otherSubscription = (Subscription) other;
            return subscriber == otherSubscription.subscriber
                    && subscriberMethod.equals(otherSubscription.subscriberMethod);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        //这个hashCode被重写了,拼接了订阅方法的签名字符串,要知道为啥这样做,就要看下SubscriberMethod#equals()的实现了
       //这么做会把本来对比int值变成了比较String类型的值
       //不用直接用Method的equals()方法,好像说是有性能问题,没看太清楚,后面了解清楚了再进行说明,先跟进今天的主题
        return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
    }
}
  • SubscriberMethodFinder#findSubscriberMethods()方法的实现:
   List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
   //这个METHOD_CACHE从下面METHOD_CACHE.put(subscriberClass, subscriberMethods)就可以看出是存储订阅者和订阅方法的映射表的,
   //比如MainActivity对应这public void onMessageEvent(MessageEvent)这个subscriberMethod
   //他是先从缓存中拿,为null时才重新进行findXxx()操作
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }
        //这个ignoreGeneratedIndex是记录是否用启动SubscriberInfoIndex机制,先明白这个SubscriberInfoIndex是用来加事件管理的缓存的就好了,具体的实现会在本文第6个部分解释
        //ignoreGeneratedIndex默认为false
        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;
        }
    }
  • SubscriberMethodFinder#findUsingReflection():
//这个方法是从订阅的subscriberClass中查找使用了@Subscribe注解的方法,比如:EventBusTestActivity中的onMessagEvent(MessageEvent)方法
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
       //FindState中封装了订阅者的Class对象,SubscriberInfo对象
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            findUsingReflectionInSingleClass(findState);
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }
  • SubscriberMethodFinder#findUsingReflectionInSingleClass()方法的实现:
  //
  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();
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        Class<?> eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            //关键是这里传入的eventType,从上文中可以看出,是我们添加了@Subscribe注解方法的第一个参数,那多个参数不行吗?这个问题先留着
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
                } 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");
            }
        }
    }
  • SubscriberMethodFinder#findUsingInfo()的实现:
private List<SubscriberMethod> 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);
    }
  • 2.2 订阅: subscribe(subscriber, subscriberMethod)方法的实现
public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        //根据订阅者对象查找SubscriberMethod集合
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                //针对每一个SubscriberMethod,这里遍历subscriber集合,其实是真正遍历是SubscriberMethod结构中事件(eventType)
                //因为到了这一步,已经有了包含eventType, method的结构集合了,下一步应该建立订阅者和事件的映射关系了
                //订阅是要将当前订阅者,所有的事件和对应的订阅者(订阅方法)建立映射关系,这样才能够将eventType对应多个订阅者的关系建立起来
                subscribe(subscriber, subscriberMethod);
            }
        }
    }
  • subscribe()方法的实现:
//源码中subscribe()的实现代码其实糅杂了三个方面的子功能,我们进行下等价转换,换成下面这样,就很清楚了
   /**
     * 分别建立:事件和订阅者集合、订阅者和事件集合的映射关系
     */
    // Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //(1)建立当前事件和订阅者一对多关系的映射表,Subscription中封装了订阅者,事件,订阅方法的集合
        buildSubscriptionsByEventTypeMap(subscriber, subscriberMethod, eventType, newSubscription);
        //(2)建立<subscriber, List<eventTypes>>映射表
        buildTypesBySubscriberMap(subscriber, eventType);

        //(3)如果是粘性事件,则在注册时需要进行发送的,这个是粘性事件的特点,不是在post()时进行发布事件,而是在register()的时候把事件发布出去
        postStickyEventToSubsriptionIfNeed(subscriberMethod, eventType, newSubscription);
    }
private void postStickyEventToSubsriptionIfNeed(SubscriberMethod subscriberMethod, Class<?> eventType, Subscription newSubscription) {
        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<Class>).
                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry<Class<?>, 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);
            }
        }
    }

    private void buildTypesBySubscriberMap(Object subscriber, Class<?> eventType) {
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);
    }

    private void buildSubscriptionsByEventTypeMap(Object subscriber, SubscriberMethod subscriberMethod, Class<?> eventType, Subscription newSubscription) {
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            //重复注册
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        //加入subscriptionsByEventType
        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }
    }

问题1:subscriber和subscriberMethods为什么要建立订阅关系?
EventBus#post(MessageEvent) 怎么才能够知道发送给谁?
下面贴一个实例:

public class EventBusTestActivity extends AppCompatActivity {
    static final String TAG = EventBusTestActivity.class.getSimpleName();
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event_bus_test);
    }

    @Override
    protected void onStart() {
        super.onStart();
        //这个注册事件的观察者直接是当前类的this对象,很暴力直接
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);   
        }
    }

    public void onClick(View view) {
        EventBus.getDefault().post(new MessageEvent());
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEventReceive(MessageEvent messageEvent) {
        Log.d(TAG, "onMessageEventReceive: ");
    }
}

3.post方法实现分析
//发送事件,这个发送事件的调用跟当前的上下文无关
 EventBus.getDefault().post(new MessageEvent());
 //注解声明的订阅方法接收事件
 @Subscribe(threadMode = ThreadMode.MAIN)
 public void onMessageEvent(MessageEvent event) {
        Log.d(TAG, "onMessageEvent: ");
 }

4.三种Poster和ThreadMode
  • 从EventBus的成员变量和EventBus::postToSubscription()方法中可以看到,进行事件的发送是通过三类Poster进行的额,那么我们看看这三类Poster的实现上有什么区别。
  • 先看下ThreadMode的定义:
public enum ThreadMode { 
	 POSTING, //发送事件和执行订阅方法在同一个线程中,实现上是直接调用invokeSubscriber(),不切换线程也不进行队列阻塞
	  MAIN, //订阅方法在主线程中执行
	  BACKGROUND, //订阅方法在子线程中执行
	  ASYNC //订阅方法在子线程中执行,没有使用生产者消费者模式
}
  • 1.HandlerPoster对应ThreadMode.MAIN
    这个是直接继承自Handler实现了一个Handler的事件处理队列,从EventBus中mHandlerPoster创建实例传入的Looper实例可以知道,这个Handler是运行在主线程的。因为Handler的事件会被切换到主线程运行,所以使用这个类型的poster不用担心调用post的位置,都可以保证订阅方法最后运行在主线程。并且还能看出来这种做法的原型是生产-消费者模式。
EventBus(EventBusBuilder builder) {
       ...
        mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
        ...
    }
final class HandlerPoster extends Handler { 
  ...
      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");
                }
            }
        }
    }
 @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            while (true) {
                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(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;
        }
    }
  ...
}
  • 2.BackgroundPoster对应ThreadMode.BACKGROUND
final class BackgroundPoster implements Runnable {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    private volatile boolean executorRunning;

    BackgroundPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                //运行在线程池中
                eventBus.getExecutorService().execute(this);
            }
        }
    }

    @Override
    public void run() {
        try {
            try {
                while (true) {
                    PendingPost pendingPost = queue.poll(1000);
                    if (pendingPost == null) {
                        synchronized (this) {
                            // Check again, this time in synchronized
                            pendingPost = queue.poll();
                            if (pendingPost == null) {
                                executorRunning = false;
                                return;
                            }
                        }
                    }
                    eventBus.invokeSubscriber(pendingPost);
                }
            } catch (InterruptedException e) {
                Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

}

跟进去之后可以发现,对于EventBus.getDefault()实例对应的,这个线程池的实现,当然EventBus是可以自己去构建一个EventBusBuilder实例的,DEFAULT_EXECUTOR_SERVICE 只是一个默认的构建器。这样就可以确定,这个poster发送出去的事件,订阅者方法都是运行在子线程中。
他是一个同步等待的消息处理队列。

private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
  • 3.AysnPoster对应ThreadMode.ASYNC
class AsyncPoster implements Runnable {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    AsyncPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        eventBus.getExecutorService().execute(this);
    }

    @Override
    public void run() {
        PendingPost pendingPost = queue.poll();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        eventBus.invokeSubscriber(pendingPost);
    }

}

可以看出,AsyncPoster的实现和简单,抛弃了生产-消费者模式,直接将一个事件入队列,然后运行时从队列中取出一个事件的订阅方法执行,那么,这种方式就会是异步的,适合耗时的异步任务,不会造成后台线程阻。


5. 解注册做了什么?
public synchronized void unregister(Object subscriber) {
        List<Class<?>> 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());
        }
    }
 private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
        List<Subscription> 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--;
                }
            }
        }
    }

6. EventBus现有的不足与完善思路

EventBus在使用起来很简单,可以说很大程度上是因为使用了反射进行了一系列内部的操作,但是我们都知道大量的反射是很损耗性能的,比如根据Class然后遍历其所有的method这种做法其实是比较低效的。EventBus3.0 之后提供了AnnnationProcessor机制

  • 配置SubscriberInfoIndex 方式:
//build.gradle
dependencies {
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}
android {
        javaCompileOptions {
            annotationProcessorOptions {
                // EventBus Apt 索引类生成位置
                arguments = [eventBusIndex: applicationId + '.MyEventBusIndex']
            }
        }
    }
}
//使用索引类
EventBus.builder().ignoreGeneratedIndex(false) // 使用 Apt 插件 默认值其实也是false
                 .addIndex(new MyEventBusIndex()) // 添加索引类
                .installDefaultEventBus();
                .register(this); // 作为默认配置
  • 会产生以下代码:
/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;

    static {
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();

        putIndex(new SimpleSubscriberInfo(EventBusTestActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onMessageEventReceive", MessageEvent.class, ThreadMode.MAIN),
        }));

        putIndex(new SimpleSubscriberInfo(MainActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onMessageEvent", MessageEvent.class, ThreadMode.MAIN),
            new SubscriberMethodInfo("onTeskRun", Runnable.class, ThreadMode.MAIN),
        }));

        putIndex(new SimpleSubscriberInfo(EventBusHelper.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onEventBus", EventBusHelper.class, ThreadMode.MAIN),
        }));

    }

    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }

    @Override
    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}
  • 6.1 跨进程通信怎么办?
     看了这里,我有个疑问,如果是要进行跨进程的消息发送,EventBus能实现吗?
    通读整个EventBus的文档和源码,完全没看见跨进程通信的影子,因为要实现跨进程起码得有个全局广播,AIDL,或者Socket吧,但是都没有。再加上官方文档在说明EventBus用途时也并没有提到EvenBus支持了跨进程通信。但是,从另一方面考虑,随着app的功能越庞大,组件化等技术的应用,多进程应用已经是很平常的事情了,跨进程通信也是刚需了,所以这也是EventBus现有功能的缺陷。如果需要扩展EventBus进行跨进程通信,可以参考github上已有的项目,

7. 小结

EventBus实现几个关键思路:

  • 设计模式:观察者模式、构建者模式、策略模式
  • 进行源码分析的几个关键类:
    • 提供对外接口的类: EventBus,
    • 封装结构的类:EventBusBuilder, Subscription, SubscriberMethod
    • 关键驱动型类:SubscriberMethodFinder 完成订阅者方法的收集器
    • 事件发送者(Poster): HandlerPoster, BackgroundPoster, AsyncPoster,生产消费者模型的应用
  • EventBus实现的主要思路
    • 1.注册流程(关键是在建立订阅关系时建立一个映射表)
      • (1) 注册
      • (2) 建立订阅者和订阅方法的映射表,查找订阅者有多少需要订阅方法(Subscrib注解声明的方法)
      • (3) 建立事件和订阅者的映射表,查找post出去的事件所有订阅者,然后把事件发出去
    • 2.事件发送流程
      • (1) 拿到缓存的事件集合
      • (2) 遍历事件,找到每一个事件的订阅者,依次把事件post到对应的订阅者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr-torto

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值