EventBus 使用

EventBus 是一款针对 Android 端优化的 publish/subscribe 消息总线。

eventbus arch

主要目的是替代Intent, Handler,BroadCast 在 Fragment,Activity,Service,线程之间传递消息,优点是开销小,代码优雅。将发送者和接收者解耦。

基本用法

引入 eventbus:

compile 'de.greenrobot:eventbus:2.4.0'

定义事件:

public class MessageEvent { /* Additional fields if needed */ }

注册事件接收者:

eventBus.register(this);

发送事件:

eventBus.post(event)

接收消息并处理:

public void onEvent(MessageEvent event) {} 

注销事件接收:

eventBus.unregister(this);

最后,proguard 需要做一些额外处理:

# EventBus
-keepclassmembers class ** {
    public void onEvent*(**);
    void onEvent*(**);
}

基本概念

作为一个消息总线,有三个主要的元素:

  • Event:事件。可以是任意类型的对象
  • Subscriber:事件订阅者,接收特定的事件。在EventBus中,使用约定来指定事件订阅者以简化使用。即所有事件订阅都都是以onEvent开头的函数,具体来说,函数的名字是onEvent,onEventMainThread,onEventBackgroundThread,onEventAsync这四个,这个和ThreadMode有关
  • Publisher:事件发布者,用于通知 Subscriber 有事件发生。可以在任意线程任意位置发送事件,直接调用 eventBus.post(Object) 方法,可以自己实例化 EventBus 对象,但一般使用默认的单例就好了:EventBus.getDefault(), 根据 post 函数参数的类型,会自动调用订阅相应类型事件的函数。

指定处理线程

默认情况下,onEvent 方法会在 post(Event) 的方法的线程中执行,但是可能会 post(Event) 是一个非UI线程,而 onEvent 方法需要更新UI,需要在主线程运行。

public void onEventMainThread(MessageEvent event) {
    textField.setText(event.message);
}

因为每个事件订阅函数都是和一个 ThreadMode 相关联的,ThreadMode 指定了会调用的函数。有以下四个 ThreadMode:

  • PostThread:事件的处理在和事件的发送在相同的进程,所以事件处理时间不应太长,不然影响事件的发送线程,而这个线程可能是UI线程。对应的函数名是 onEvent。
  • MainThread: 事件的处理会在UI线程中执行。事件处理时间不能太长,这个不用说的,长了会ANR的,对应的函数名是onEventMainThread。
  • BackgroundThread:事件的处理会在一个后台线程中执行,对应的函数名是 onEventBackgroundThread,虽然名字是 BackgroundThread,事件处理是在后台线程,但事件处理时间还是不应该太长,因为如果发送事件的线程是后台线程,会直接执行事件,如果当前线程是 UI 线程,事件会被加到一个队列中,由一个线程依次处理这些事件,如果某个事件处理时间太长,会阻塞后面的事件的派发或处理。
  • Async:事件处理会在单独的线程中执行,主要用于在后台线程中执行耗时操作,每个事件会开启一个线程(有线程池),但最好限制线程的数目。

使用 Sticky Events

某些时候,我们并不希望发布出来的Event立即被消费掉,而是等到时机成熟。比如说,在一个详情页点赞之后,产生一个VoteEvent,VoteEvent并不立即被消费,而是等用户退出详情页回到商品列表之后,接收到该事件,然后刷新Adapter等。其实这就是之前我们用startActivityForResult和onActivityResult做的事情。

那么怎么用EventBus来模拟这样的情况呢?这就需要另外一个强大的机制,Sticky Event.

和普通的Event不同,当发布一个Sticky Event,需要使用postSticky方法:

EventBus.getDefault().postSticky(new VoteEvent(obj));

上面的代码发布了一个点赞的Sticky Event.

...
EventBus.getDefault().registerSticky(this);
...

public void onEventMainThread(VoteEvent event) {
    // TODO update adapter
}

EventBus 的 registerSticky 方法在每次执行的时候,都会去查询一次 Sticky Event,并调用响应的方法处理。

除了 registerSticky 方法来触发Sticky Event 之外,我们还可以通过 getStickyEvent 方法来获取响应的 Sticky Event 来进行处理。比如,我们可以在 onResume 方法里面检查 EventBus 里面是否有 VoteEvent 的Sticky Event,从而进行处理:

@Override
public void onResume() {
    super.onResume();
    VoteEvent voteEvent = EventBus.getDefault().getStickyEvent(VoteEvent.class);
}

3.0 beta 版本的变化

3.0 版本目前还在 beta 阶段,主要变化时使用注解代替基于惯例的 onEvent 方法,用法如下:

@Subscribe(threadMode = ThreadMode.MainThread)
public void onVoteEvent(VoteEvent event) {
}

进阶

想要探索更幽深的世界,就去看源码吧:

EventBus源码研读

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

推荐阅读更多精彩内容

  • 前言:EventBus出来已经有一段时间了,github上面也有很多开源项目中使用了EventBus。所以抽空学习...
    Kerry202阅读 1,282评论 1 2
  • 概述 EventBus是一个Android事件发布/订阅框架,通过解耦发布者和订阅者简化Android事件传递,这...
    刘涤生阅读 78,394评论 6 57
  • 简介 EventBus是一个Android事件发布/订阅框架,通过解耦发布者和订阅者简化Android事件传递,这...
    lwd45阅读 356评论 0 0
  • 近来在看平凡的世界,一发不可收拾,非常震撼心灵,心里面的那种触动我真的表达不清楚。已经很久没有看到这么好看的电视剧...
    文淑阅读 1,341评论 0 12
  • 1.EventBus是一个基于观察者模式的事件发布/订阅框架,开发者通过极少的代码去实现多个模块之间的通信,而不需...
    newszhu阅读 414评论 0 0