EventBus使用详解

EventBus这个开源框架出来已经很久了,深的很多开发者青睐,由greenrobot组织贡献(该组织还贡献了greenDAO),是一个Android事件发布/订阅轻量级框架,通过解耦发布者和订阅者简化Android事件传递,EventBus可以代替Android传统的Intent,Handler,Broadcast或接口函数,在Fragment,Activity,Service线程之间传递数据,执行方法。

其最大的特点就是:代码简洁,是一种发布订阅设计模式(观察者设计模式)。在没有EventBus之前我们通常用广播来实现监听,或者自定义接口函数回调,但有的场景我们也可以直接用Intent携带简单数据,或者在线程之间通过Handler处理消息传递。但无论是广播还是Handler机制远远不能满足我们高效的开发,广播是四大组件之一,许多系统级的事件都是通过广播来通知的,比如说网络的变化、电量的变化,短信发送和接收的状态,但是广播是相对消耗时间和资源的,Handler虽然简单但高复发的内存泄漏困扰很多初级开发者,那么EventBus会很好消除这些缺点,那么本节我们来了解一下他的使用方法,很简单的哦,相信以后你也会爱上的。

EventBus3.0源码地址:https://github.com/greenrobot/EventBus


EventBus重要方法和类:

Event 传递的事件对象

Subscriber  事件的订阅者

Publisher  事件的发布者

ThreadMode 定义函数在何种线程中执行

他们之间的关系如图:

那么具体该怎么操作呢? 请往下看

1)在需要订阅事件的地方注册事件,可以是Activity或者Fragment中

EventBus.getDefault().register(this@MainActivity)

2)创建Event消息类 —定义事件模型

该类可以不继承任何基类也不需要实现任何接口,

class MessageEvent(val progress: Int)

这里我用Kotlin写的,所以大家看起来会有些不习惯,不过相信大家看起来不会有问题,因为android的api是不变得,只是kotlin写法稍有改变,会java的同学学起Kotlin也会很容易,由于Google现在墙裂推荐Kotlin,作为Android开发者还是不能掉队,所以大家有时间也多尝试这门小众语言,继续我们的内容,

3)产生事件、发送事件

EventBus.getDefault().post(MessageEvent(time))

在我们需要传递消息的地方将数据封装到消息类Event中发送出去,这里我们就将数据发送出去了,我们怎么接受这条消息呢? 接着看

4)消费事件,处理消息

@Subscribe(threadMode = ThreadMode.MAIN)

fun onEventMessage(event: MessageEvent) {

progress!!.progress = event.progress

}

@Subscribr()注解标识我们的线程模型,这里我们要更新进度条的进度,所以制定消费事件的线程为主线程,在3.0之前,EventBus还没有使用注解方式。消息处理的方法也只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,分别代表四种线程模型。而在3.0之后,消息处理的方法可以任意命名,这是个很大方便,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为PostThread),需要注意的是事件处理函数的访问权限必须为public,否则会报异常。

这里我们更新UI中进度条进度,大家可以在此取出消息内容执行自己的逻辑。

当然,我们要记得取消订阅,跟广播逻辑很相似。

override fun onDestroy() {

super.onDestroy()

EventBus.getDefault().unregister(this@MainActivity)

}


回到上面话题线程模型处,我们来了解这几个线程模型具体含义:

在EventBus的事件处理函数中需要指定线程模型,即指定事件处理函数运行所在的想线程。在上面我们已经接触到了EventBus的四种线程模型。那他们有什么区别呢?在EventBus中的观察者通常有四种线程模型,分别是PostThread(默认)、MainThread、BackgroundThread与Async。

PostThread:如果使用事件处理函数指定了线程模型为PostThread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为PostThread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。

MainThread:如果使用事件处理函数指定了线程模型为MainThread,那么不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。该方法可以用来更新UI,但是不能处理耗时操作。

BackgroundThread:如果使用事件处理函数指定了线程模型为BackgroundThread,那么如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。

Async:如果使用事件处理函数指定了线程模型为Async,那么无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行UI更新操作。

EventBus黏性事件:

EventBus除了普通事件也支持粘性事件,这个有点类似广播分类中的粘性广播。本身粘性广播用的就比较少,为了方便理解成订阅在发布事件之后,但同样可以收到事件。订阅/解除订阅和普通事件一样,但是处理订阅函数有所不同,需要注解中添加sticky

= true,

findViewById(R.id.button).setOnClickListener {

Thread(Runnable {

time = 0

while (time <= 100) {

EventBus.getDefault().postSticky(MessageEvent(time))

SystemClock.sleep(500)

time += 10

} }).start()

EventBus.getDefault().register(this@MainActivity)

//粘性事件,在需要的时候注册,接受最后一条消息

}

//EventBus.getDefault().register(this@MainActivity)

}

这里我们没有在onCreate()中注册EventBus,我们是收不到广播的,其实这里我们可以另外添加一个按钮,在按钮点击事件里面注册EventBus,我们这里把注册这一步放在发送事件的后面,也可以按照刚才说的那种方式把注册步骤放到另外一个button点击事件里面。

对于粘性广播我们都比较清楚属于常驻广播,对于EventBus粘性事件也类似,我们如果不再需要该粘性事件我们可以移除

EventBus.getDefault().removeStickyEvent(MessageEvent(time))

或者调用移除所有粘性事件

EventBus.getDefault().removeAllStickyEvents();

如果对粘性事件还不是很熟悉的同学可以再去看看广播的内容,也可以将广播内容跟EventBus做个总结,设计思想及其相似,都是基于观察者模式,只是粘性体现在能够收到订阅之前发送的消息。但是它只能收到最新的一次消息,比如说在未订阅之前已经发送了多条黏性消息了,然后再订阅只能收到最近的一条消息。

看到这里,你是不是对EventBus已经有了很好的了解,EventBus使用很简单,但是确实给项目和开发者带来很大的方便,有机会大家可以尝试看看EventBus的源码,从源码角度更深层次了解EventBus的强大,本节就到这儿,我们下次再见!!!  晚安

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

推荐阅读更多精彩内容

  • 前言:EventBus出来已经有一段时间了,github上面也有很多开源项目中使用了EventBus。所以抽空学习...
    Kerry202阅读 1,280评论 1 2
  • 前言:EventBus出来已经有一段时间了,github上面也有很多开源项目中使用了EventBus。所以抽空学习...
    Lauren_Liuling阅读 48,416评论 23 155
  • 前言 最近在公司做一个类似于手机工厂模式的一个项目,用来检测其他各个App是否正常工作,所以要求是尽可能的轻量级,...
    Luckily_Liu阅读 1,169评论 2 8
  • 本文的EventBus,是指greenrobot的 EventBus, 主要以EventBus3.0 讲解; 什么...
    Simon_z阅读 5,141评论 2 2
  • 目录 1.概述 2.实战 1.基本框架搭建 2.新建一个类FirstEvent 3.在要接收消息的页面注册Even...
    慕涵盛华阅读 10,485评论 2 16