EventBus这个开源框架出来已经好久了,深的不少开发者青睐,由greenrobot 组织贡献(该组织还贡献了greenDAO),是一个Android事件发布/订阅轻量级框架,经过解耦发布者和订阅者简化Android事件传递,EventBus能够代替Android传统的Intent,Handler,Broadcast或接口函数,在Fragment,Activity,Service线程之间传递数据,执行方法。
java
其最大的特色就是:代码简洁,是一种发布订阅设计模式(观察者设计模式)。在没有EventBus以前咱们一般用广播来实现监听,或者自定义接口函数回调,但有的场景咱们也能够直接用Intent携带简单数据,或者在线程之间经过Handler处理消息传递。但不管是广播仍是Handler机制远远不能知足咱们高效的开发,广播是四大组件之一,许多系统级的事件都是经过广播来通知的,好比说网络的变化、电量的变化,短信发送和接收的状态,可是广播是相对消耗时间和资源的,Handler虽然简单但高复发的内存泄漏困扰不少初级开发者,那么EventBus会很好消除这些缺点,那么本节咱们来了解一下他的使用方法,很简单的哦,相信之后你也会爱上的。android
EventBus3.0源码地址:github.com/greenrobot/…git
EventBus重要方法和类:github
他们之间的关系如图:
设计模式
那么具体该怎么操做呢? 请往下看api
EventBus.getDefault().register(this@MainActivity)
复制代码
该类能够不继承任何基类也不须要实现任何接口,bash
class MessageEvent(val progress: Int)复制代码
这里我用Kotlin写的,因此你们看起来会有些不习惯,不过相信你们看起来不会有问题,由于android的api是不变得,只是kotlin写法稍有改变,会java的同窗学起Kotlin也会很容易,因为Google如今墙裂推荐Kotlin,做为Android开发者仍是不能掉队,因此你们有时间也多尝试这门小众语言,继续咱们的内容,网络
EventBus.getDefault().post(MessageEvent(time))
复制代码
在咱们须要传递消息的地方将数据封装到消息类Event中发送出去,这里咱们就将数据发送出去了,咱们怎么接受这条消息呢? 接着看框架
@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,不然会报异常。ide
这里咱们更新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除了普通事件也支持粘性事件,这个有点相似广播分类中的粘性广播。自己粘性广播用的就比较少,为了方便理解成订阅在发布事件以后,但一样能够收到事件。订阅/解除订阅和普通事件同样,可是处理订阅函数有所不一样,须要注解中添加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的强大,本节就到这儿,咱们下次再见!!! 晚安