一、简介:
EventBus是一款本地组件间通信框架
组件间通信框架star量第一:14.8k,在大型项目的Activities,fragments,Threads,Services都可以看到它的使用场景,尽管EventBus在向未创建的组件传递事件时有些局限,仅适合在“活着的”组件间传递消息,但仍不妨碍它活跃在各个大型项目各个场景里。
-
官网地址:http://greenrobot.org/eventbus/documentation/how-to-get-started/
-
github:https://github.com/greenrobot/EventBus
1.1 三个角色
- Event:事件,它可以是任意类型,EventBus会根据事件类型进行全局的通知。
- Subscriber:事件订阅者,在EventBus 3.0之前我们必须定义以onEvent开头的那几个方法,分别是
onEvent
、onEventMainThread
、onEventBackgroundThread
和onEventAsync
,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe
,并且指定线程模型,默认是POSTING
。 - Publisher:事件的发布者,可以在任意线程里发布事件。一般情况下,使用
EventBus.getDefault()
就可以得到一个EventBus对象,然后再调用post(Object)
方法即可。
1.2 四种线程模型
EventBus3.0有四种线程模型,分别是:
- POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一个线程。
- MAIN:表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
- BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
- ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
二、EventBus的基本用法:
2.1添加依赖:
implementation 'org.greenrobot:eventbus:3.1.1'
如果要使用索引 还需添加
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ]
}
}
}
dependencies {
...
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}
2.2如何使用:
1.首先定义一个数据类用于EventBus数据间的通信
eg:
public class MessageEvent{
private String message;
public MessageEvent() {
}
public MessageEvent(String message){
this.message=message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "MessageEvent{" +
"message='" + message + '\'' +
'}';
}
}
2.在activity中注册事件
EventBus.getDefault().register(this);
3.使用普通方式接收信息(注意: 注解的方法 必须是 public)
不是public 可能引发:its super classes have no public methods with the @Subscribe annotation 错误
@Subscribe(threadMode = ThreadMode.MAIN)
public void Event(MessageEvent messageEvent) {
Log.d("tgw2", "Event:非粘性事件 "+messageEvent.toString());
tvEvent.setText(messageEvent.getMessage());
}
4.非粘性事件发送消息注意发送的必须与上面订阅的 ---Event方法中的参数一致
MessageEvent messageEvent = new MessageEvent();
messageEvent.setMessage(editText.getText().toString());
EventBus.getDefault().post(messageEvent);
5.完整例子:
- 首先在oncreated()方法中注册
- 通过点击事件开启一个新的Activity---SecondActivity
- 在SecondActivity通过点击事件使用 EventBus.getDefault().post(messageEvent); 发送消息 返回MainActivity
- 在MainActivity中的 onDestroy() 方法中 将 EventBus 注销
public class MainActivity extends AppCompatActivity {
private Button btEventBus;
private Button btStick;
private TextView tvEvent;
private boolean isStart = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btEventBus = findViewById(R.id.bt_eventbus);
tvEvent = findViewById(R.id.tv_event);
btStick = findViewById(R.id.bt_stick);
//注册
EventBus.getDefault().register(this);
//跳转另一个活动 给当前页面的tvEvent赋值
btEventBus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
//非粘性事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void Event(MessageEvent messageEvent) {
Log.d("tgw2", "Event:非粘性事件 "+messageEvent.toString());
tvEvent.setText(messageEvent.getMessage());
}
@Override
protected void onDestroy() {
super.onDestroy();
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this);
}
//粘性事件取消注册
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if (stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}
}
SecondActivity:
public class SecondActivity extends AppCompatActivity {
private Button btReturn;
private EditText editText;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_main);
btReturn = findViewById(R.id.bt_eventbus);
editText = findViewById(R.id.edit_event);
btReturn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MessageEvent messageEvent = new MessageEvent();
messageEvent.setMessage(editText.getText().toString());
Log.d("tgw", "onClick: " + messageEvent.getMessage() );
//注意返回的值必须是类对象
//1.非粘性事件 发送的值将会在MainActivity中获取到
EventBus.getDefault().post(messageEvent);
finish();
}
});
}
}
2.3使用粘性事件
1.它的特点就是可以获取上一次发送的消息 (能够收到订阅之前发送的消息就是不在oncreated方法中注册通过button点击事件控制注册事件)
异同点:
非粘性---
之前我们需要先注册 在发送消息 这样才可以接收(不然就算你先发送 在注册 也需要再次发送才可以接收)
粘性---
我们可以先使用
EventBus.getDefault().postSticky(new MessageEvent("粘性"));
发送消息,在通过
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class); String stick = stickyEvent.getMessage();
接收消息 但是此时我们还收不到消息 之后还需注册:
EventBus.getDefault().register(MainActivity.this);
这样就得到的信息
2.粘性 使用 sticky = true 参数 至于 priority = 2 适用于定义优先级 类似广播的
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN,priority = 2)
使用方法 :我们 先点击 btEventBus 中的事件 再点击 btStick 中的点击事件 就可以接收到信息了
粘性注销 在onDestroy()中
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if (stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}
3.优先级
关注 Event(MessageEvent messageEvent) 和 EventPriority(MessageEvent messageEvent) 方法
我在EventPriority(MessageEvent messageEvent) 方法中使用了 EventBus.getDefault().cancelEventDelivery(messageEvent);
方法用于 消息截断
完整代码:
public class MainActivity extends AppCompatActivity {
private Button btEventBus;
private Button btStick;
private TextView tvEvent;
private boolean isStart = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btEventBus = findViewById(R.id.bt_eventbus);
tvEvent = findViewById(R.id.tv_event);
btStick = findViewById(R.id.bt_stick);
//发送粘性事件
btEventBus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().postSticky(new MessageEvent("粘性"));
}
});
//注册粘性
btStick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isStart) {
EventBus.getDefault().register(MainActivity.this);
isStart = false;
}
}
});
}
//粘性事件 能够收到订阅之前发送的消息(就是不在oncreated方法中注册通过button点击事件控制注 册事件)
//注意返回的值必须是类对象
//接受从SecondActivity返回的值
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN,priority = 1)
public void Event(MessageEvent messageEvent) {
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
String stick = stickyEvent.getMessage();
Log.d("tgw2", "Event:粘性事件优先级低 " + messageEvent.toString() + "---" + stick);
tvEvent.setText(messageEvent.getMessage());
}
//优先级threadMode 参数值要一样(意思是订阅方法是一样的)
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN,priority = 2)
public void EventPriority(MessageEvent messageEvent) {
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
String stick = stickyEvent.getMessage();
Log.d("tgw2", "Event:粘性事件优先级高 " + messageEvent.toString() + "---" + stick);
tvEvent.setText(messageEvent.getMessage());
// 终止事件的继续分发(感觉无用)
EventBus.getDefault().cancelEventDelivery(messageEvent);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this);
}
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if (stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}
}
参考:
https://www.jianshu.com/p/25388d6446bf
https://www.jianshu.com/p/f9ae5691e1bb
https://www.jianshu.com/p/e7d5c7bda783