EventBus3.0使用详解

前言:

EventBus是最近接手的一个项目上在用的开源库,但是我这个EventBus菜鸟,之前还没用过,还没好好感受过它的好处,前几天刚刚看完源码,对EventBus有了一个大体的了解,看完源码之后,感觉此库真是好处多多啊,不吹不黑,不服来辩,哈哈哈,不吹了,根据官方doc,记录一下EventBus的使用。

优势:

使用一个开源库,我们总要知道他的优势所在,要不然那么多开源库,为毛非要用这个,你说是这个理不。那我们就看一下他的优势所在,
想知道官方的介绍的可以去这里查看:EventBus官方介绍

EventBus是安卓发布/订阅事件总线的优化

翻译过来其实也就这么核心几条:

1. 简化组件间的通信
(1).对发送和接受事件解耦
(2).可以在Activity,Fragment,和后台线程间执行
(3).避免了复杂的和容易出错的依赖和生命周期问题
2. 让你的代码更简洁
3. 更快
4. 更轻量(jar包小于50K)
5. 实践证明已经有一亿多的APP中集成了EventBus
6. 拥有先进的功能比如线程分发,用户优先级等等

基本结构:

盗图一张:

基本用法:

1. 添加gradle依赖

compile 'org.greenrobot:eventbus:3.0.0'
Step 1: Define events

Events 就是一个普通的JavaBean,没有任何特殊要求,例如:

public class MessageEvent {
    public final String message;

    public MessageEvent(String message) {
        this.message = message;
    }
}
Step 2: Prepare subscribers

准备subcriber的回调method,来处理post event,从EventBus_3开始,用注解@Subscribe来定义subscriber的回调method,方法名可以任意定义
例如:

 // This method will be called when a MessageEvent is posted
    @Subscribe
    public void onMessageEvent(MessageEvent event){
        Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
    }

    // This method will be called when a SomeOtherEvent is posted
    @Subscribe
    public void handleSomethingElse(SomeOtherEvent event){
        doSomethingWith(event);
    }

Subscribers与BroadcastReceiver类似,需要register和unregister,只有注册了EventBus,回调方法才起作用,在Android中,一般与Activity的生命周期绑定在一起

官方demo:

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

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}
Step 3: Post events

前面准备好,这里就可以任意post event。所有已注册EventBus的subscriber只要event_type相匹配,都可以收到该event

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

ThreadMode用法:

当牵扯到线程间通讯时,特别是,主线程,后台线程,耗时操作线程,等线程间的通讯时,我们就必须倍加小心,好在EventBus很强大,已经考虑到了,我们只需要根据具体的需求去配置,不同的线程模式ThreadMode即可:

ThreadMode源码:

public enum ThreadMode {
    POSTING,
    MAIN,
    BACKGROUND,
    ASYNC;
}

接着,逐一分析下,各个模式适合的场景:

POSTING
这个模式最简单,也是EventBus默认的模式,也就是说:post event和handle event在同一个线程

@Subscribe(threadMode = ThreadMode.POSTING) // ThreadMode is optional here
//默认为Posting,可以不指定
public void onMessage(MessageEvent event) {
    log(event.message);
}
MAIN


当指定threadMode=Main时,此时,handle event是运行在UI线程的,
如果,post event也是在UI线程,就跟Posting模式一样,
Warning:使用此模式,不能堵塞UI线程

// Called in Android UI's main thread
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(MessageEvent event) {
    textField.setText(event.message);
}
BACKGROUND
当指定threadMode=Background时,
如果 post event不在UI线程,那么handle event 会在此线程回调;
如果 post event在UI线程,EventBus使用一个后台线程,按顺序分发所有事件。
Warning:使用此模式,不能堵塞后台线程

// Called in the background thread
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessage(MessageEvent event){
    saveToDisk(event.message);
}
ASYNC
当指定threadMode=Async时,
handle event始终独立于UI线程和post event所在的线程,即:和post event 不在同一线程,
也不在UI线程。此模式适合耗时任务:e.g.:网络链接。
Warning:避免触发大量的长时间运行的异步线程,来限制并发线程的数量。
EventBus使用Thread pool高效 的使用线程


// Called in a separate thread
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessage(MessageEvent event){
    backend.send(event.message);
}

Configuration用法:

当默认的EventBus不足以满足需求时,EventBusBuilder就上场了,EventBusBuilder允许配置各种需求的EventBus

例如1:
当没有subscribers的时候,eventbus保持静默:
EventBus eventBus = EventBus.builder().logNoSubscriberMessages(false)
    .sendNoSubscriberEvent(false).build();

例如2:
配置异常:
默认情况下:eventbus捕获onevent抛出的异常,并且发送一个SubscriberExceptionEvent 可能不必处理

EventBus eventBus = EventBus.builder().throwSubscriberException(true).build();
配置默认的eventbus单例

官方推荐:在application类中,配置eventbus单例,保证eventbus的统一

例如:配置eventbus 只在DEBUG模式下,抛出异常,便于自测,同时又不会导致release环境的app崩溃
EventBus.builder().throwSubscriberException(BuildConfig.DEBUG).installDefaultEventBus();

Sticky Events用法:

前面说的一般的post event,正常流程,必须是先register,然后post event,handle event才能起作用。但是当我们post event时,还没有subcriber怎么办?但是又想后注册的subscriber,能收到消息,这时sticky event就开始大显身手了。

Warning:EventBus会把最后一个sticky event记录在内存中,然后分发给subscriber

来看下官方的Demo

1 post sticky event:

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

2 启动一个新的Activity,准备subscriber,注册后,
所有的sticky subscriber的回调方法,会马上获得之前的sticky event

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

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

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}
Getting and Removing sticky Events manually

如上所述,当subscriber注册后,最后一个sticky event会自动匹配。但是,有些时候,主动去检查sticky event会更方便,并且 sticky event 需要remove,阻断继续传递。

官方demo

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

2中sticky event使用方法都可行,看业务需要和个人习惯,选择合适的使用方法

Priorities and Event Cancellation用法:

大多数情况下,eventbus不需要改变线程优先级,或者取消event,但是不排除少数情况,需要改变线程优先级。

Subscriber Priorities

官方demo

//priority默认为0,不同ThreadMode下的分发流程不受优先级的影响
//优先级高的可以优先获得消息
@Subscribe(priority = 1);
public void onEvent(MessageEvent event) {
…
}
Cancelling event delivery

如果,不希望后续的subcriber收到消息,可以在收到消息后,调用cancelEventDelivery(Object event) 取消消息的后续传递。

官方demo

@Subscribe
public void onEvent(MessageEvent event){
// Process the event
…

EventBus.getDefault().cancelEventDelivery(event) ;
}

Note:一般情况下,event的取消发生在高优先级的subscriber

ProGuard 混淆规则

-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

AsyncExecutor

关于AsyncExecutor的用法,还是看官方文档吧,因为这个我也没用过

Subscriber Index

这是eventbus3.0新增的功能,是对原有功能的优化,为register提供了一种比反射更快速的方案,也就是对应源码中的private List findUsingInfo(Class

小结

看完官方文档介绍,对eventbus的使用基本上就没什么问题了,再加上看了3天的源码解析,对eventbus的内部结构总算是有了一个大概的了解,如果有不对的地方,欢迎指正,另外对eventbus源码解析有高见的,也欢迎留言交流

EventBus源码解析推荐2篇我认为比较好的,也可以帮助阅读源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值