EventBus使用笔记

来源:互联网 发布:北津学院教务网络 编辑:程序博客网 时间:2024/06/11 12:07

今天迁移一篇比较强大的开源工具使用笔记,最近忙着准备简历了,没怎么写代码,心塞。。

EventBus

image

EventBus使用发布-订阅模式,即消息的发布方和消息的接收方并不直接通信,而是通过EventBus中转。

以下内容参阅EventBus Document

建议对EventBus有一个初步认识后就不要再四处找教程了,直接去看官方文档会更加清晰。

添加依赖

compile 'org.greenrobot:eventbus:3.0.0'

Step 1:自定义Event类

简单的model类,在这个类中你可以包含任何你想发送出去的信息,比如我通过异步请求获得了一个人的姓名,年龄,我想把这两条信息发送到主线程中某个活动中去,那么这个消息类就可以这么写:

public class People{  public String name;  public int age;  public People(String name, int age){    this.name = name;    this.age = age;  }}

Step 2:把消息发出去

EventBus.getDefault().post(Tom)

其中Tom是一个People对象,里面封装了name和age。

Step 3:订阅信息(接收消息)

在接受消息的类中,首先注册,即调用EventBus.getDefault().register(this);,然后添加接收消息的方法。方法名不限制,但是参数列表必须是唯一,且必须是该订阅者想要接收的消息类型。

@Subscribe(threadMode = ThreadMode.MAIN)public void onMessageEvent(People peolpe){  //在这里将接收到刚才发出去的Tom对象}

EventBus工作原理:

  1. EventBus怎么知道我要把消息发到哪里去呢?即,拿着消息的EventBus面对众多的订阅者,如何判断把这条消息发给谁?

    答:根据订阅者的方法参数的类型。这也是为什么第一步需要自定义消息类型的原因。比如说上面的例子中,onMessageEvent()方法接受People参数,那么所有类型为People的消息都会往它这里派。如果有两个订阅者都指明要接收People类型的消息呢,答案是两个都会收到。当然你可以为二者设定优先级,还可以设定是否阻断消息,就像有序广播那样。下面将详细介绍。

  2. EventBus对发送的消息有什么要求吗?

    答:是有要求的。就如同我们看到的那样,post方法接受且只接受一个Object参数,因此我们必须将要发送的所有内容封装在一个消息对象中,这也是为什么要自定义消息类型的原因。当然如果我要发送的消息已经封装过了,比如我想发一个List对象或者一个简单的String对象出去,那你也可以直接发,传给post()即可。

跨线程通信

不得不说EventBus用来跨线程通信简直太方便了,之前总是用的AsyncTask快被我完全抛弃了。

对于子线程向UI线程发送异步请求结果这种常见需求,我们只需要使用EventBus在子线程中把消息发出去,然后在UI线程中将subscriber的threadMode指定为Main就行了。实际上,subscriber的threadMode一共有四种,下面一一分析。

  1. ThreadMode.POSTING

    这也是默认的模式。使用这个模式的Subscriber将在发送消息时的线程中被调用,即发送消息在哪个线程,这个Subscriber就会在哪个线程被调用。

  2. ThreadMode.MAIN

    顾名思义,Subscriber将在主线程中被调用,不管发送消息的线程是否是主线程。上面的例子中就是用了这种模式。

  3. ThreadMode.BACKGROUND

    这种模式下,如果发送消息时的线程本身就不是主线程,那么Subscriber将在同样的线程中被调用;如果发送消息是在主线程中进行的,那么EventBus会开一个子线程,在子线程中调用这个Subscriber。

  4. ThreadMode.ASYNC

    这种模式下,总是会在另外一个线程中调用Subscriber,该线程一般不同于发送消息的线程或主线程。一般要避免trigger大量的这种Subscriber。针对这种情况,EventBus会使用线程池技术来复用线程。

事件分发的优先级控制与事件的拦截

上面说了,EventBus是根据Subscriber的消息接受类型来判断将消息派发给谁的,那就有可能出现两个Subscriber订阅了相同类型的事件,这种情况下,两个Subscriber都会同时收到事件。同时,我们也可以对其分别指定优先级,决定谁先收到事件,并且先收到事件的Subscriber还能决定是否姜时间消费掉。

@Subscribe(priority = 1,threadMode = ThreadMode.MAIN)public void onMessageEvent(People peolpe){  //在这里将接收到刚才发出去的Tom对象  //do sth...  //决定是否截断事件  EventBus.getDefault().cancelEventDelivery(event) ;}

上面的代码中指定了该Subscriber的priority为1,如果不指定的话为0.priority越高的Subscriber将会在其他相同的Subscriber之前收到事件,并且可以调用cancelEventDelivery()方法将事件消费掉,也就是不再向后传播,非常类似于有序广播的abortBroadCast()方法。