簡介
普通事件:通過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