EventBus

1.添加依赖

compile 'org.greenrobot:eventbus:3.1.1'

2.三步学会

2.1定义事件

先定义事件VO,和普通的Java Bean没有区别:

public class MessageEvent {
    public final String message;
    public MessageEvent(String message) {
        this.message = message;
    }
}

2.2 定义事件接收者

使用@Subscribe这个注解,方法名不做任何限制:

// 接收者在UI线程中执行操作
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}

//接收者与发送者在同一个线程中 
@Subscribe
public void handleSomethingElse(SomeOtherEvent event) {
    doSomethingWith(event);
}

别忘注册和取消注册事件,这可以防止内存泄露:

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}

2.3 发送一个事件

可以在任何地方发送一个事件:

EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

3.线程切换

3.1 ThreadMode: POSTING

这是EventBus的默认工作模式,发布者接收者在同一个线程中,需要注意的是接收者的逻辑不能太复杂,因为有可能阻塞主线程。

// Called in the same thread (default)
// ThreadMode is optional here
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessage(MessageEvent event) {
    log(event.message);
}

3.2 ThreadMode: MAIN

3.3 ThreadMode: MAIN_ORDERED

顾名思义,事件按序发送。只有事件处理完成了,才会接收事件(官网文档前后矛盾,后续自己验证哪个订阅先执行吧),适合修改界面等敏感操作。

3.4 ThreadMode: BACKGROUND

订阅者在后台线程中执行逻辑,如果事件发送者不在主线程那么会直接复用当前线程,如果发送者在主线程,那么EventBus用一个线程来按顺序处理事件,所以接收者也不要在这种模式下为所欲为,因为可能阻塞后台线程(个人感觉鸡肋,不如不要)。

3.5 ThreadMode: ASYNC

为所欲为吧,专为耗时操作设计。事件接收及发送均无需等待,要慎重,避免开启过多线程, EventBus 使用线程池来高效复用线程。

4. 粘性事件(Sticky Events)

就是事件发送了,但是我现在注册也要收到这个事件。
看一下例子吧:
假设现在发送一个事件:

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));

现在启动一个新的Activity,相关代码如下:

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

// UI updates must run on MainThread
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {   
    textField.setText(event.message);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);    
    super.onStop();
}

4.1 主动获取/删除粘性事件

有的时候你可能并不需要注册EventBus,只是要获得这个粘性事件:

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
}

removeStickyEvent方法很有意思,如果你将事件class穿进去,他会返回先前持有的粘性事件,使用这个特性,上述代码可以这样修改:

MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
    // Now do something with it
}

是不是简洁了很多?当然前提是你需要杀掉这个粘性事件。

5.事件的优先级和取消

大部分情况下不需要这样做,但一些场景可能需要这样做:当App处于前台时,一个事件可能导致UI做出改变,但是App不可见时需要另外一种逻辑。

5.1订阅优先级

@Subscribe(priority = 1);
public void onEvent(MessageEvent event) {
    ...
}

注意:高优先级的先接收到事件,默认为0,但是只有ThreadMode相同时才有效,即不切换线程模式。

5.2 取消事件继续发送

// Called in the same thread (default)
@Subscribe
public void onEvent(MessageEvent event){
    // Process the event
    ...
    // Prevent delivery to other subscribers
    EventBus.getDefault().cancelEventDelivery(event) ;
}

事件通常被高优先级的订阅者取消,取消事件的方法必须处于 ThreadMode.PostThread模式下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值