在Android之间各组件通信的时候,有时候进行通信不太方便,自己就用到了EventBus。
EventBus主要用于应用程序内各组件间、组件与后台线程间的通信。
EventBus主要有三个组成部分
事件:(Event)可以是任意类型的对象。通过事件的发布者将事件进行传递。
事件订阅者(Subscriber):接收特定的事件。
事件发布者(Publisher):用于通知 Subscriber 有事件发生。可以在任意线程任意位置发送事件
1.需要添加依赖
implementation 'org.greenrobot:eventbus:3.0.0'
2.构造事件消息类(Event),每一个消息类对应一种时间,这里我门定义了一张图片的url地址。
public class RandomTimerEvent {
public String random;
public RandomTimerEvent(String random) {
this.random = random;
}
3.在获取返回信息的Activity.java中的onCreate进行注册,在onDestory进行解除注册。
EventBus.getDefault().register(this);
//在OnDestory中解除注册
EventBus.getDefault().unregister(this);
4.在需要返回信息的地方写入
//在这里我传入了一个图片地址url[i]
EventBus.getDefault().post(new RandomTimerEvent(url[i]));
5.在获取返回信息的Activity.java中获取信息,这里是采用了注解的方式
@Subscribe(threadMode = ThreadMode.MAIN)
//这里我是用了Glide框架加载图片,Glide框架的最简单使用加载图片,不懂得自行百度
public void RandmMsg(RandomTimerEvent randomTimerEvent){
Glide.with(MainActivity.this).load(randomTimerEvent.random).error(R.mipmap.sb).into(iv);
}
以上就是EventBus的简单使用了,下面说一下EventBus的进阶使用。、
1.线程模式
关于ThreadMode一共有四种方式:
PostThread,MainThread,BackgroundThread以及Async。
PostThread:事件的处理在和事件的发送在相同的进程,所以事件处理时间不应太长,不然影响事件的发送线程。
MainThread: 事件的处理会在UI线程中执行。事件处理时间不能太长,长了会造成ANR的。
BackgroundThread:如果事件是在UI线程中发布出来的,那么事件处理就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么事件处理直接在该子线程中执行。所有待处理事件会被加到一个队列中,由对应线程依次处理这些事件,如果某个事件处理时间太长,会阻塞后面的事件的派发或处理。
Async:事件处理会在单独的线程中执行,主要用于在后台线程中执行耗时操作,每个事件会开启一个线程。
2.事件的优先级
EventBus事件的优先级类似于广播的优先级,优先级越高,优先获得消息。
@Subscribe(priority = 10)
public void onToastEvent(InfoEvent event){
Log.e(TAG,"优先级展示");
}
也可以阻止其他事件的传递
@Subscribe(priority = 10)
public void onToastEvent(InfoEvent event){
Log.e(TAG,"优先级展示");
EventBus.getDefault().cancelEventDelivery(event);
}
3.粘性事件
订阅在发布事件之后,但同样可以收到事件,简单理解就是,你现在还没有订阅,但是之前已经有发布的事件,当订阅后,之前发布的事件可以接收到。举个例子:当我们打开一个App,我们已经接收到了后台传过来需要展示的信息,但是用户还没有进行登录,这个事件已经发布了,用户还没有登录,我们也没有订阅,当用户登录之后进行订阅,不需要浪费时间再向后台请求数据,可以直接获取信息。粘性时间与普通事件有些区别,下面进行展示。
需要在注解中加入sticky = true
@Subscribe(threadMode = ThreadMode.MAIN,**sticky = true**)
public void RandmMsg(RandomTimerEvent randomTimerEvent){
Glide.with(MainActivity.this).load(randomTimerEvent.random).error(R.mipmap.sb).into(iv);
}
同样发布事件也变了
EventBus.getDefault().postSticky(new RandomTimerEvent(url[i]));
如果不需要粘性事件我们可以进行解除,就是当用户没有登录的时候,进行事件的解除。
EventBus.getDefault().removeStickyEvent(RandomTimerEvent.class);
或者调用移除所有粘性事件
EventBus.getDefault().removeAllStickyEvents();
好了,EventBus的使用暂时就是这些了,如果有不足,或者错误,需要补充的,欢迎提出。
补充一些我在使用EventBus出现的问题:
1.当我们在OnCreate或者其它周期注册的时候可以使用下面方法,判断是否注册,如果没有注册,再进行注册,这样防止如果没有取消注册获取屏幕翻转导致的重复注册,出现两次接收数据。
if(!EventBus.getDefault().isRegistered(this)){
EventBus.getDefault().register(this);
}
同理,当我们取消注册的时候,我们可以在onDestory中使用如下取消注册
if(EventBus.getDefault().isRegistered(this)){
EventBus.getDefault().unregister(this);
}
2.我们在fragment中使用EventBus的时候,当我们注册的时候使用应该使用
EventBus.getDefault().register(this);
而不是使用
EventBus.getDefault().register(getActivity());
否则会报错
3.当我们在一个Activity或者fragment使用EventBus注册的时候必须写接收方法,否则程序会报错崩溃