上一篇文章(EventBus官方教程)翻译自官网,显得有些生硬。这篇就开始自己的理解,如有不对之处,还望众大神慧眼识珠,多多指出!
一、简介
相比大家看这篇文章对EventBus有了一定的了解了 如果没有,那么请看我上一篇文章,(官方的话还是很权威的嘛!)EventBus官方教程
二、使用
前言 -- 导入 implementation 'org.greenrobot:eventbus:3.1.1'
EventBus 事件总线,无非也就四件事 :注册,发送消息,接收消息,解除注册。
就以上看来,和我们的广播是不是很相似呢?不,我想说的是EventBus相当于 广播,服务的结合体。为什么这么说呢,看完这篇文章你就懂了!
首先,我们先定义一个Java Object(其实就是事件Module)
public class EventMessage {
public String msg;
public EventMessage(String name) {
this.msg = name;
}
}
接着我们需要一个事件处理的Object
class EventSrc1{
@Subscribe
public void EventBusDef(EventMessage event){
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void EventBus(EventMessage event){
}
}
可以看出 没什么特别的。只是多了一个 Subscribe 注解,注解的参数稍后带大家过一遍。
以上仅仅一些准备工作,相信大家都没有问题
接下来,如何使用EventBus进行事件传递呢?
还是开篇的几句话,注册,发送消息,接收消息,解除注册。
- 注册
EventBus.getDefault().register(obj);注意,注册的方法至少有一个方法带了Subscribe注解,否则将会报错
- 发送消息
EventBus.getDefault().post(new EventMessage("hello world"));- 接收消息 注册对象 带Subscribe注解的方法
- 解除注册
EventBus.getDefault().unregister(obj);
举个栗子:
public class MainActivity extends AppCompatActivity {
EventSrc1 reg1 = new EventSrc1();
private TextView tv;
int cont = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.message);
}
public void reg1(View view) {
cont = 0;
EventBus.getDefault().register(reg1);
}
public void unreg(View view) {
EventBus.getDefault().unregister(reg1);
}
public void post(View view) {
EventBus.getDefault().post(new EventMessage("我是即时消息,谁注册谁接收!"));
}
class EventSrc1{
@Subscribe
public void EventBusDef(EventMessage event){
cont++;
tv.setText(event.msg+cont);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void EventBus(EventMessage event){
cont++;
tv.setText(event.msg+cont);
}
}
}
以上便是简单使用,接下来说说粘性消息
粘性消息;
通过以上的例子可以看出,仅注册事件了的才可以接收消息,否则消息将会销毁。
EventBus还支持另一种消息,没错,就是粘性消息。该消息不会被发送之后就销毁,而是存储在内存当中。当有事件注册之后,会推送到注册的对象方法中。因为该消息会一直在内存当中。所以我们不需要的时候要移除该消息。
那么该怎么使用呢?
一样,还是注册,定义事件源。接收消息,解除注册。
- 注册
EventBus.getDefault().register(obj);注意,注册的方法至少有一个方法带了Subscribe注解,否则将会报错
- 发送粘性消息
EventBus.getDefault().postSticky(new EventMessage("hello world"));- 接收消息 注册对象 带Subscribe注解的方法
- 解除注册
EventBus.getDefault().unregister(obj);- ** 移除事件**
EventBus.getDefault().removeStickyEvent(stickyEvent);
举个栗子:
public class MainActivity extends AppCompatActivity {
EventSrc2 reg2 = new EventSrc2();
private TextView tv;
int cont = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.message);
}
public void reg2(View view) {
cont = 0;
EventBus.getDefault().register(reg2);
}
public void unreg(View view) {
EventBus.getDefault().unregister(reg2);
}
public void post(View view) {
EventBus.getDefault().post(new EventMessage("我是即时消息,谁注册谁接收!"));
}
public void sticky(View view) {
EventBus.getDefault().postSticky(new EventMessage("我是粘性消息,没注册也能接收!"));
}
class EventSrc2{
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void StickyEventBus(EventMessage event){
cont++;
tv.setText(event.msg+cont);
}
}
}
以上便是EventBus的全部使用方法了,那么有些同学可能会疑惑注解这块,接下来就带着大家来聊一聊注解这块吧!
注解这块其实没什么聊的,只是定义了接收消息的标识,大家用过反射应该都知道原理,这里并不带大家去深究源码。只是告诉大家注解中有哪些配置选项
首先 注解中有三个参数 threadMode ,sticky,priority
先来最简单的 :priority 该参数指定优先级,优先级越高就越先接收到消息,默认值0
sticky 该参数指定是否可以接收粘性事件 默认值为false
threadMode 共四个值
ThreadMode: POSTING
订阅服务器将在同一线程中调用该事件。默认值就是这个. 事件传递是同步完成的,一旦发布完成,所有订阅服务器都将被调用。 这个线程模式意味着最小的开销,因为它避免了线程的完全切换。因此,这是已知的简单任务的推荐模式,在不需要主线程的情况下是非常短的时间。使用此模式的事件处理程序应快速返回,以避免阻塞线程,这可能是主线程。例子:
// Called in the same thread (default)
// ThreadMode is optional here
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessage(Object event) {
}
ThreadMode: MAIN
订阅者将在Android的主线程中调用(有时称为UI线程),如果发布线程是主线程,则将直接调用事件处理程序方法(如THealMyth.PoST描述的同步)。使用此模式的事件处理程序必须快速返回,以避免阻塞主线程。例子:ple:
// Called in Android UI's main thread
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(MessageEvent event) {
textField.setText(event.message);
}
ThreadMode: MAIN_ORDERED
订阅者将在Android的主线程中被调用。 事件总是被排队等待以后传递给订阅服务器。因此,帖子的调用将立即返回。 这使得事件处理更加严格和更加一致。(这样的名字 MAIN_ORDERED).例如,如果在主线程模式下的事件处理程序中发布另一个事件,则第二事件处理程序将在第一个事件处理程序之前完成。(因为它被同步调用——将它与方法调用进行比较). 用 MAIN_ORDERED, 第一个事件处理程序将完成,然后第二个事件处理程序将在稍后的时间点被调用(一旦主线程具有容量)。
使用此模式的事件处理程序必须快速返回,以避免阻塞主线程。例子:
// Called in Android UI's main thread
@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
public void onMessage(MessageEvent event) {
textField.setText(event.message);
}
ThreadMode: BACKGROUND
将在后台线程中调用订阅服务器。如果发布线程不是主线程,则将在POST线程中直接调用事件处理程序方法。如果发布线程是主线程,EngestBUS使用一个将依次传递所有事件的单个后台线程。使用此模式的事件处理程序应尽量快速返回,以避免阻塞后台线程。
// Called in the background thread
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessage(MessageEvent event){
saveToDisk(event.message);
}
ThreadMode: ASYNC
事件处理程序方法在单独的线程中调用。这始终与发布线程和主线程无关。发布事件永远不会等待使用此模式的事件处理程序方法。事件处理程序方法应该使用此模式,如果它们的执行可能需要一些时间,例如用于网络访问。避免同时触发大量长时间运行的异步处理程序方法来限制并发线程的数量。EnvivBUS使用线程池来有效地从完成的异步事件处理程序通知中重用线程。
// Called in a separate thread
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessage(MessageEvent event){
backend.send(event.message);
}
EventBus完整例子:
public class MainActivity extends AppCompatActivity {
EventSrc1 reg1 = new EventSrc1();
EventSrc2 reg2 = new EventSrc2();
private TextView tv;
int cont = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.message);
}
public void reg1(View view) {
EventBus.getDefault().register(reg1);
}
public void reg2(View view) {
EventBus.getDefault().register(reg2);
}
public void unreg(View view) {
cont = 0;
EventBus.getDefault().unregister(reg1);
EventBus.getDefault().unregister(reg2);
}
public void post(View view) {
EventBus.getDefault().post(new EventMessage("我是即时消息,谁注册谁接收!"));
}
public void sticky(View view) {
EventBus.getDefault().postSticky(new EventMessage("我是粘性消息,没注册也能接收!"));
}
class EventSrc1 {
@Subscribe
public void EventBusDef(EventMessage event) {
cont++;
tv.setText(event.msg + cont);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void EventBus(EventMessage event) {
cont++;
tv.setText(event.msg + cont);
}
}
class EventSrc2 {
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void StickyEventBus(EventMessage event) {
cont++;
tv.setText(event.msg + cont);
}
}
}










网友评论