首先得明确EventBus是用来做什么的呢?
由greenrobot 组织贡献(该组织还贡献了greenDAO),一个Android事件发布/订阅轻量级框架
功能:通过解耦发布者和订阅者简化Android事件传递
EventBus可以代替Android传统的Intent,Handler,Broadcast或接口函数,在Fragment,Activity,Service线程之间传递数据,执行方法
特点:代码简洁,是一种发布订阅设计模式(观察者设计模式)。
先看简单的使用案例:
现要从MainActivity的生命周期onStart()方法中发送一条String类型的消息到SecondActivity,而此时SecondActivity尚未创建,我们如何将值从MainActivity传递到SecondActivity呢?看以下代码,就一目了然;
在MainActivity中
点击MainActivity中的按钮,跳转到SecondActivity
再看SecondActivity中对这条消息的处理
就这样,在SecondActivity未创建的时候,给它传值,SecondActivity依旧收的到;
我们带着问题,从源码的角度逐一分析;
第一步:注册
先看EventBus的注册:
可以看到,这里是一个单例双重校验锁的实现,返回EventBus的实例
regiest方法中的参数是一个订阅者,也就是我们所说的Activity、Fragment
并由regiest中的参数,获取到订阅者的实例
并执行了 List<SubscriberMethod>subscriberMethods=subscriberMethodFinder.findSubscriberMethods(subscriberClass);
再看SubscriberMethodFinder的findSubscriberMethods方法
- 如果有Map缓存中有值,就直接获取
- 如果 ignoreGeneratedIndex为true 就 findUsingReflection(subscriberClass) 通过反射获取
- 如果 ignoreGeneratedIndex为false ,就 findUsingInfo(subscriberClass) 获取
- 最后
- subscriberMethods 为空,内部报异常(对外是不会提示的)
- subscriberMethods 不空,把对应的key为 subscriberClass, value为subscriberMethods 加入到 Map缓存中
而 subscribe(subscriber,subscriberMethod)方法又做了什么呢?看下面
第二步:取消事件订阅
取消订阅事件源码
第三步:发送消息或对象
postSticky(),发送一个粘性事件的消息,具体看源码
源码中的注释翻译如下:将给定的事件发布到事件总线并保持事件不变(因为它是粘性的)。事件类型的最新粘性事件保存在内存中,供订阅服务器使用{@link Subscribe#sticky()}进行未来访问。
这也正好解释了最开始案例中MainActivity向尚未实例化的SecondActivity发了一条消息,而在SecondActivity实例化后,能接收到的缘故;
再看普通的Post()方法,将给定的事件发布到事件总线
第四步,接受发送过来的对象或message
ThreadMode的五种模式
POSTING
订阅者将在发布事件的同一线程中被直接调用。这是默认设置。事件交付意味着最少的开销,因为它完全避免了线程切换。因此,对于不需要主线程就可以在很短时间内完成的简单任务,这是推荐的模式。使用此模式的事件处理程序必须快速返回,以避免阻塞提交线程(可能是主线程)。
MAIN
在Android上,订阅者将在Android的主线程(UI线程)中被调用。如果发布线程是主线程,订阅者方法将被直接调用,从而阻塞发布线程。否则,事件将排队等待交付(非阻塞)。使用此模式的订阅服务器必须快速返回,以避免阻塞主线程。如果不在Android上,其行为与{@link # post}相同。
MAIN_ORDERED
在Android上,订阅者将在Android的主线程(UI线程)中被调用。与{@link #MAIN}不同的是,事件将始终排队等待交付。这确保了post调用是非阻塞的。
BACKGROUND
在Android上,订阅者将在后台线程中被调用。如果发布线程不是主线程,订阅方方法将直接在发布线程中调用。如果发布线程是主线程,则EventBus使用单个后台线程,它将按顺序交付所有事件。使用此模式的订阅者应尝试快速返回,以避免阻塞后台线程。如果不是在Android上,总是使用一个后台线程。
ASYNC
订阅服务器将在单独的线程中调用。这总是独立于发布线程和主线程。发布事件从不使用此模式等待订阅方方法。如果订阅者方法的执行可能需要一些时间,例如网络访问,则应使用此模式。避免同时触发大量长时间运行的异步订阅方方法来限制并发线程的数量。EventBus使用线程池来有效地重用来自已完成的异步订阅方通知的线程。
磨刀不误砍柴工,弄明白这几种模式,也便于在开发过程中灵活使用;
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)注解方法中三个参数
1、ThreadMode 这个上面说了
2、stick 如果为真,则将最近的粘性事件(使用@link EventBus#postSticky(Object)}发布)传递给此订阅服务器(如果事件可用)。
3、priority 订阅者优先影响事件交付的顺序。在相同的提交线程中({@link ThreadMode}),高优先级的订阅者将比低优先级的订阅者更早收到事件。默认的优先级是0。注意:优先级不影响不同{@link ThreadMode}的订阅者之间的发送顺序!
今天就看这么多,希望闲来无事的大佬们,指点一二;