EventBus 这一篇还不够

参考网站

EventBus 官网

环境配置

Gradle:

compile 'org.greenrobot:eventbus:3.0.0'

Maven:

<dependency>
    <groupId>org.greenrobot</groupId>
    <artifactId>eventbus</artifactId>
    <version>3.0.0</version>
</dependency>

原理介绍

67020902-bc93-4e78-af81-ab9ba2d85307.png

这张图是比较形象的EventBus的工作原理图,来自EventBus官网。我们可以形象的理解 EventBus 就是一个老司机,他有一个手册,手册上写了路线有很多个餐馆。这个时候有一个乘客上车,掏出手机给老师机看高德地图上的一条路线说我要去这儿,老司机和餐馆老板有私下交易,所以他会拉着你挨个经过这些餐馆。

上面有一些字是加粗的,老司机代表 EventBus,他在系统中是一个单例模式。所有的事件都要经过老司机,EventBus维护这一个HashMap,及一个手册,手册中记录了很多的路线,每条路线上有很多餐馆,路线就是我们的 事件(Message,这里不够形象,但是大概理解吧),好,路线上有很多个餐馆,餐馆就是 订阅者,源码中直接用这样的结构存储 Map<Object, List<Class<?>>>,Object就是事件, List 里面存的订阅者,当某种事件发生时,这条线上的所有订阅者都会收到消息。至于还有一个乘客,发布事件的人,其实就是 EventBus 本身,通过 EventBus.getDefault.post( Message ) 发送事件。

不知你理解了没有,反正我理解了。如果不理解,那就看代码吧!

入门例子

1. 定义 MessageEvent 对象

MessageEvent.java

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

2. 定义 处理 MessageEvent对象方法

MainActivity.java

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}

3. 注册和取消订阅

MainActivity.java

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

4. 发布MessageEvent

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

理清思路

根据代码,我们再来理解刚开始给的那张图。如果使用EventBus这个老司机,那么系统中就只会出现这么一个老司机,它是单例模式,猜都能猜到,如果不信,你可以跟到源代码EventBus.getDefault()中看,很基本的双重锁写法:

static volatile EventBus defaultInstance;

public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

然后通过 老司机.post(MessageEvent event) 出来的事件首先会传给老司机,因为系统中只有老司机知道有哪些订阅者,并且他们订阅的是什么事件,他是通过注解的形式知道,@Subscribe表示该方法是要处理事件的,但是处理哪种事件呢?后面方法的参数决定 MessageEvent event。当然还不要忘了一定要给老司机 注册他才认识你 EventBus.getDefault().register(this);,看源码发现在在调用register的时候,EventBus才会去找这个类中的 @Subscribe

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}

然后老司机拿到了 事件,并且看了看他的注册表中有哪些家伙订阅了这个事件,当事件发生时,就把事件传给他们,让他们去处理。我觉得这样写应该所有人都能明白吧,至于底层的原理,可以看看EventBus的源码。

ThreadMode 介绍

还记得上面的HelloWorld例子中我们用到了 @Subscribe(threadMode = ThreadMode.MAIN), MAIN 表示UI主线程,EventBus包括以下4种:

  • ThreadMode.POSTING默认模式,效率高,收到消息就执行。让订阅方法工作在与发布消息同一个线程中。

  • ThreadMode.MAIN:让订阅方法始终切换到 UI主线程中执行

  • ThreadMode.BACKGROUND:启动新线程,让订阅方法在新线程中执行

  • ThreadMode.ASYNC:异步模式,也是工作在新线程中,但是EventBus提供了线程池的管理,避免线程不停创建。

其实ThreadMode就是为了让我们更好的在线程中切换,大家都知道Android中UI主线程后后台线程的区别,以前我们都要使用 Handler,AsyncTask 等来处理,代码繁重,现在只需要一个注解就搞定了,是不是很爽。

这也让我想到了 RxJava 中也提供了线程切换这样的功能,流式编程就显得更加的简洁明了,并且还不需要这样那样的注册,大总管之类的东西,所以现在大家都喜欢用RxJava。

EventBus其他功能介绍

StickyEvent

第一个是粘性事件,普通的事件我们通过post发送给EventBus,发送过后之后当前已经订阅过的方法可以收到。但是如果有些事件需要所有订阅了该事件的方法都能执行呢?例如一个Activity,要求它管理的所有Fragment都能执行某一个事件,但是当前我只初始化了3个Fragment,如果这时候通过post发送了事件,那么当前的3个Fragment当然能收到。但是这个时候又初始化了2个Fragment,那么我必须重新发送事件,这两个Fragment才能执行到订阅方法。

粘性事件就是为了解决这个问题,通过 postSticky 发送粘性事件,这个事件不会只被消费一次就消失,而是一直存在系统中,知道被 removeStickyEvent 删除掉。那么只要订阅了该粘性事件的所有方法,只要被register 的时候,就会被检测到,并且执行。订阅的方法需要添加 sticky = true 属性。

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {   
    textField.setText(event.message);
}

订阅权限 Subscriber Priorities

你可以通过 在@Subscribe(priority = 1)中添加 priority 来定义订阅的权限。权限越高的方法会在收到后越先执行。默认的 priority = 0

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

取消事件分发

当你收到一个事件,并且调用 cancelEventDelivery 后,那么这个事件不会再往下分发,要知道,有可能不止一个方法订阅了该消息哦,取消后后面的方法就都收不到消息了。

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

还有其他的就自己看官网吧

写在最后的话

我也是才看EventBus,其实用起来的话感觉确实比以前的Handler那些机制要好用。但是EventBus这个大总管的方式其实我不太喜欢,如果项目不停迭代,代码越来越多,管理Message就变得很繁琐,出错也不好排查。而且这个大总管是单例哦,如果App一直运行,或并发数目比较多时,可能性能上会有一些问题,当然这只是自己的猜想而已,我还没有实践过。

老司机开开车,其实我不是老司机,学习一点内容,分享分享,希望能抛砖引玉。自己也写过很多的内容,总结下来也有一些经验,对于我们这些初学者来说,请记住一定学习一个新技术,新框架的时候,从官网入手,英文就英文,多看两遍就回了。所以我写过的每一篇笔记都是附上官网地址的,所以你还在等什么,看官网去吧,光看这点是不够的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容