普通事件:通过post()方法发出的普通事件,会被已经注册的订阅者接收到,若订阅者是在消息发送之后才注册,那么是不会接收到该事件的
粘性事件:而粘性事件是可以被事件发出之后才注册的订阅者接收到,也可以在事件发出之后通过主动查询获取事件内容。粘性事件实现原理其实是把最近的事件缓存到内存中,之后注册的订阅者还可以查询出来
比如在AActivity中发送一个粘性事件Event,然后打开BActivity,在BActivity中注册Event的粘性事件订阅者,在注册后马上可以接收到该事件。而如果是普通事件的话是接收不到的,因为订阅者是在消息发送之后才注册的。这就是粘性事件的方便之处。
先定义一个事件类型
public class MessageEvent {
public String message;
public MessageEvent(String message) {
this.message = message;
}
}
发送粘性事件
EventBus.getDefault().postSticky(new MessageEvent("野猿新一"));
// 订阅
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
// 接收粘性事件的方法
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
Toast.makeText(context, event.message, Toast.LENGTH_SHORT).show();
}
// 取消订阅
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
粘性事件除了可以通过订阅获取外,还可以通过getStickyEvent()方法主动获取
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
还可以通过removeStickyEvent()方法移除粘性事件,表示消费了该事件,避免后面重新订阅还会再重复收到该事件
if(stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}
removeStickyEvent方法还有一个重载方法,出入的参数是类而不是对象,该方法会移除该类型最近的粘性事件,并返回该事件。所以以上获取粘性事件并移除的代码还可以简化如下
MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// Now do something with it
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post(new MessageEvent("普通事件"));
}
});
findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().postSticky(new MessageEvent("粘性事件"));
}
});
}
public static class MessageEvent {
public String message;
public MessageEvent(String message) {
this.message = message;
}
}
// 订阅
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
// 接收粘性事件的方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void onNormalEvent(MessageEvent event) {
Log.d("StickyEvents", "onNormalEvent:" + event.message);
Toast.makeText(this, "onNormalEvent:" + event.message, Toast.LENGTH_SHORT).show();
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onStickyEvent(MessageEvent event) {
Log.d("StickyEvents", "onStickyEvent:" + event.message);
Toast.makeText(this, "onStickyEvent:" +event.message, Toast.LENGTH_SHORT).show();
}
// 取消订阅
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
}
2019-12-27 14:22:10.091 24825-24825/com.him.hisapp D/StickyEvents: onNormalEvent:普通事件
2019-12-27 14:22:10.101 24825-24825/com.him.hisapp D/StickyEvents: onStickyEvent:普通事件
2019-12-27 14:22:11.574 24825-24825/com.him.hisapp D/StickyEvents: onNormalEvent:粘性事件
2019-12-27 14:22:11.588 24825-24825/com.him.hisapp D/StickyEvents: onStickyEvent:粘性事件
从以上测试代码及打印的日志可知:
若粘性事件订阅者在普通事件发送前注册,也是可以收到到普通事件的
若普通事件订阅者在粘性事件发送前注册,也是可以接收到粘性事件的
Sticky Events