EventBus直译过来,叫做消息总线 , 可以简化应用程序内各组件间、组件与后台线程间的通信. 比如,Activity之间的通信 ,主线程与子线程的通信 ,Service于Activity的通信,Fragment与Fragment的通信, 都可以使用该开源库方便的处理. 使用该框架,你只需要考虑谁是订阅者, 谁是发布者就可以了.
EventBus -- 基本使用
EventBus源码 -- 注册
EventBus源码 -- 发送消息
EventBus源码 -- 注销
gradle依赖####
compile 'org.greenrobot:eventbus:3.0.0'
笔者在使用时为3.0版本
记住 是org开头, org org org, 不是de
基本概念####
EventBus的github中写到了使用方法, 但对于完全没有接触过的人来说, 理解起来还是有些困难的. 用一张图给大家描述一下.
自助火锅都吃过的哈, 厨房吧处理好的食材放到传送带上, 交钱入座的客户就可以在传送带上拿到食材
也许我们的GreenRobot也是受此启发.......
类比一下我们的EventBus, 总体来说的模式就是: 发送者把事件发送到总线中, 订阅者订阅了之后就可以收到消息了
1. 消息 (菜品)
2. 订阅者(顾客)
3. 发送者(厨房)
吃过火锅的朋友们到这里应该基本理解EventBus的使用方法了,接下来就是具体的代码编写. 这里先简略的写个demo举例子
步骤####
Demo
Activity与Fragment
需求描述: 在Activity中嵌入一个Fragment,点击Activity中的按钮,可以发送消息到Fragment中并展示出来
-
准备消息: 就是一个实体类的写法
-
在订阅者(Fragment)中,进行注册和注销, 相当于缴费就坐
-
发送消息(把菜放到传送带中)
-
在Fragment中接收消息,并使用(就做的客人拿到菜品)
按照以上的流程,你就学会了最基本的EventBus的用法,接下来上效果图
详谈 EventBus
会了最基本的使用之后,我们来正经的梳理一下
- EventBus的三要素:
- Event 事件,可以为任意类型的对象
- Subscriber 事件订阅者, EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING),四种线程模型下面会讲到。
- Publisher 事件发布者. 可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法。可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就好了,根据post函数参数的类型,会自动调用订阅相应类型事件的函数。
- 线程模型, 也就是在注解中写的threadMode:
-
POSTING: 如果使用事件处理函数指定了线程模型为POSTING,发布事件和接收事件在同一个线程进行。
注意 : 在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。 -
MAIN 事件的处理会在UI线程中执行。
注意 : 不要有耗时操作,会ANR。 -
BACKGROUND 如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。
注意 : 在此事件处理函数中禁止进行UI更新操作。 - ASYNC 无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。
- 粘性事件
普通的消息是发送就可以接收, 而粘性事件是先暂存在内存中, 要求在使用时再拿到数据. 其实套路也是大同小异的.
- 发送事件为发送粘性事件:
EventBus.getDefault().postSticky(new EventBusStickyMessage("我是主页面发送过来的粘性事件"));
- 接收事件时使用注解为: 这里的sticky=true表示开启粘性事件
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
- 注销时候,同时要注销掉粘性事件:
那些坑
- 在@Subscribe注解下的方法必须为public, 否则会报错.
- 订阅者的接收参数必须为包装类
- EventBus的注册是在订阅者(接收消息)中写的, 因为EventBus的注册必须与@Subscribe注解写在同一个类, 否则会报错.
- EventBus在注册的时候,会将注册者的订阅事件信息保存在一个HashMap中 , 也就是说,可以多次注册. 在不及时销毁的情况下, 发布一个消息, 可能会引起消息传递混乱. 在这里给出以下建议:
- 将EventBus的注销写在onPause中,注册写在OnResume中
- 在每次注册注销的时候引入一个boolean变量记录是否注册, 避免重复注册. 记得在注销的时候重置变量.
- 由于EventBus的耦合性太低 , 在多次使用时候 ,往往不知道哪里可以接收, 极大的降低了可读性 , 这里推荐一个插件 , 可以方便的标记EventBus的发布与接收:EventBus3 IntelliJ Plugin, 效果图如图所示:
点击按钮即可找到发布或者接收的代码片段.(个人感觉 , 同时加上注释吧最好)
具体的情况请参照实际需求使用