EventBus是GreenRobot开发的Android和Java的开源库,使用发布者/订阅者模式进行解耦合。EventBus使组件之间的通信只需几行代码即可搞定,极度解耦并且简化了代码,消除依赖关系并加快应用程序开发。这里是EventBus的官网:https://greenrobot.org/eventbus/。在介绍EventBus的通信方法之前,首先会介绍常规的通信方法,比如说设置监听或者是使用广播等方式,以此来说明常规的方法都有其弊端,然后使用EventBus来完成组件之间的通信,通过案例体会EventBus在组件通信过程中的优势。
GreenRobot组织开发的这款开源库,从这个项目的名称就充分体现了它的功能,EventBus有两个单词组成——Event和Bus。那什么是Event呢?在Android平台上有非常多的事件类型,其中最常见的就是触控事件,当触控事件发生的时候,应用程序需要做出一些响应,从而来和用户进行交互。应用程序的各个组件之间以及应用程序和用户之间都需要进行通信。有了消息通信,应用程序才是可交互的。那接下来的问题就是如何进行通信呢?也就是说如何去发送和处理消息呢?
在回答这个问题之前,我们先来看一下什么叫做Bus。现在请调整思维,脱离软件开发领域,进入到日常生活场景。我们经常需要从一个地方到达另外一个地方,比如说出发地是上海。目的地是杭州。一开始我们位于出发地,如果靠自己的双脚走路。你知道路线就是一个不小的挑战。通常情况下,我们会借助公共交通系统,有了这样的运输系统,我们就只需要做两件事儿:第一件事儿就是从出发地上车;第二件事儿就是在目的地下车。整个运输过程当中,这个交通系统对我们来说是不可见的,我们并不需要了解其内部细节。只需要做两件事儿,第一件就是从出发地上车,第二件就是在目的地下车。
那现在我们回到软件开发领域,这次我们需要运输的对象不再是自己。而是事件消息,这个事件有一个发送方,具体来说它就会是某一个Java类当中的某一个方法,我们是在这个方法中来发送消息。那还有一个订阅方,订阅方就是表示我对这个事件感兴趣。我要接收这个事件消息,我要处理这个事件消息,借助EventBus这个运输系统。我们需要做两件事儿,第一件事儿就是在这个发送方去发布消息,然后EventBus的运输系统就会来负责在内部来传递这个消息。对于我们需要关注的第二件事儿,就是在订阅方来以订阅和处理这个事件。整个过程当中EventBus就是一个黑盒子,我们只需要做两件事儿。第一件事儿就是发布事件,第二件事儿就是订阅和处理事件。这次应该EventBus已经有了一个初步的认识,它就是一个能够帮助我们完成组件间通信的工具。需要掌握如何使用EventBus完成事件的订阅和发布,从而借助这样的一个开源库轻松的实现组件间的相互通信。
常规通信方法
在介绍这些方式之前,先介绍一下项目Demo的功能,
Listener监听的方式
MainActivity.java
1 | public class MainActivity extends AppCompatActivity { |
activity_main.xml 布局文件
1 |
|
PublisherDialogFragment.java
1 | public class PublisherDialogFragment extends DialogFragment { |
这样做虽然实现了功能,但是耦合性还是比较高的,对于事件的发布方必须定义接口,而且当时间越来越多的时候我们就需要定义越来越多的接口和方法,这样事件的接收方和发送方耦合在了一起,当两个组件中存在依赖的时候,耦合关系就建立了,其中一个修改的话就会影响到另外一个组件,耦合度过高是不利于软件开发的,所以还有什么其他的通信方式呢?接下来看看本地广播这种形式。
本地广播的方式
为什么使用本地广播呢?因为只是在这个应用内部进行通信,其他App不需要监听这个广播,所以采用本地广播即可:
MainActivity中注册广播监听,注意在Activity销毁时取消广播监听,MainActivity.java:
1 | ...... |
PublisherDialogFragment.java
1 | ...... |
对于广播通信的方式对于发送方需要创建Intent,并且双方必须规定好Intent的Action,而且必须规定好Intent中的数据字段。对于消息的接收方,又需要解析Intent中的数据,可以说还是比较麻烦了。而且广播都是运行在UI线程,如果想要在后台线程需要我们手动作切换,使用起来就不是很方便了。
使用EventBus通信
下面来直接使用EventBus进行组件之间的通信,也就是上面的例子,看看可以省略多少代码呢?
使用EventBus重点需要三步:定义事件 -> 在订阅方进行订阅 -> 发布方发布事件,首先需要引入依赖:
1 | implementation group: 'org.greenrobot', name: 'eventbus', version: '3.1.1' |
定义一个事件,其实就是一个普通的Java类:
1 | public class MyEvent { |
MainActivity.java中订阅事件:
1 | import org.greenrobot.eventbus.EventBus; |
PublisherDialogFragment.java作为发布方发布事件:
1 | public class PublisherDialogFragment extends DialogFragment { |
EventBus线程模式
EventBus3.0有四种线程模型,分别是:
1、POSTING:默认模式,表示事件处理函数的线程跟发布事件的线程在同一个线程。
2、MAIN:表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
3、BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
4、ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
POSTING模式
POSTING模式是EventBus默认的模式,我们在使用的时候不需要再订阅者的方法的注解后面添加模式选项,但是这种只能在同一个线程中接收,也就是说,如果是在主线程中发布消息就只能在主线程中接收消息,如果是在子线程中,那么也只能在相同的子线程中去接收消息,在下面的例子中,演示的是50%的随机几率在新线程发送事件,50%的随机几率在UI线程发送事件。
订阅者代码:(MainActivity.java)
1 | // POSTING 模式 |
发布者代码:(PublisherDialogFragment.java)
1 | if(Math.random() > 0.5f){ |
MAIN模式
MAIN模式保证了订阅者指定的那个接收方法肯定要主线程中执行,可以放心的在里面执行更新UI操作。无论发布者是在主线程中还是在那一条子线程中发布消息,这边接收的都在主线程中。
订阅者代码:(MainActivity.java)
1 | // MAIN 模式 |
发布者代码:(PublisherDialogFragment.java)
1 | if(Math.random() > 0.5f){ |
MAIN_ORDER模式
MAIN_ORDER模式与MAIN模式类似,但是稍微有点区别:MAIN_ORDER模式和MAIN一样都是在主线程中,不同的就是不需要等带订阅方完成订阅,发布方就可以继续自己的代码运行:
订阅者代码:(MainActivity.java)
1 | // MAIN_ORDER 模式 |
发布者代码:(PublisherDialogFragment.java)
1 | Log.i(TAG, "onCreateDialog: before @" + SystemClock.uptimeMillis()); |
同样的代码当使用MAIN模式时:(即@Subscribe(threadMode = ThreadMode.MAIN)
):
同样的代码当使用MAIN_ORDER模式时:(即@Subscribe(threadMode = ThreadMode.MAIN_ORDER)
):
BACKGROUND
订阅者代码:(MainActivity.java)
1 | // BACKGROUND 模式 |
发布者代码:(PublisherDialogFragment.java)
1 | if(Math.random() > 0.5f){ |
ASYNC
表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作:
订阅者代码:(MainActivity.java)
1 | // ASYNC 模式 |
发布者代码:(PublisherDialogFragment.java)
1 | if(Math.random() > 0.5f){ |
下面是整个工程全部的代码:
1 | public class MainActivity extends AppCompatActivity { |
PublisherDialogFragment.java
1 | public class PublisherDialogFragment extends DialogFragment { |
activity_main.xml
1 |
|
以上的内容就是EventBus的基本使用方法与线程模式的总结了。
参考资料
1、EventBus: Events for Android
- 本文作者: Tim
- 本文链接: https://zouchanglin.cn/1024374978.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!