EventBus3.0 使用这一篇文章就够了

因为EventBus 3.0 和之前的版本差异较大,下面介绍的内容是基于EventBus3.0 。EventBus,是一个基于Publish/Subscribe的事件总线框架, 这里不做过多详细介绍。

下面是EventBus工程和文档地址:

GitHub : https://github.com/greenrobot/EventBus
官方文档:http://greenrobot.org/eventbus/documentation

配置

这里介绍一下配置。

  1. 基本配置:
    在app 工程下的build.gradle 中添加依赖:

    dependencies {
        ......  // 省略部分依赖
        implementation 'org.greenrobot:eventbus:3.1.1'
    }
    
    
  2. 如果使用索引(index)在app 工程下的build.gradle 中添加依赖:

    android {
        defaultConfig {
            .... // 
        
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [ eventBusIndex : 'com.cfox.eventbusdemo.index.EventBusIndex' ]
                }
            }
        }
    }
     
    dependencies {
        implementation 'org.greenrobot:eventbus:3.1.1'
        annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
    }
    

快速使用

  1. 创建消息类
    这个类可以任意定义, 作为传输使用

    public class MessageObjectOne {
    
        private String info;
        public String getInfo() {
            return info;
        }
    
        public void setInfo(String info) {
            this.info = info;
        }
    }
    
  2. 注册
    注册使用EventBus实例register(Object subscriber)方法进行注册。

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }
    
  3. 注销
    注销使用EventBus实例unregister(Object subscriber)方法进行注册。

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }
    
  4. 订阅接事件
    订阅接收方法使用注解@Subscribe

    @Subscribe(threadMode = ThreadMode.MAIN, priority = 2, sticky = true)
    public void subMessageOne(MessageObjectOne msgOne) {
        Log.d(TAG, "subMessageOne: " + msgOne.getInfo());
    }
    

    上面代码发现,注解@Subscribe 有三个参数,还有不同的值。下面会介绍

  5. 发布消息

    MessageObjectOne object = new MessageObjectOne();
    object.setInfo("hello world");
    EventBus.getDefault().post(object);
    

@Subscribe参数

threadMode

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

  • ThreadMode.MAIN:
    事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。

  • ThreadMode.BACKGROUND:如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。

  • ThreadMode.ASYNC:无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。

priority
订阅方法的优先级影响订阅方法的执行顺序。优先级越高越被先执行。
sticky
如果设置为true则该订阅事件为粘性事件(后面会详细介绍)。

使用索引(index)

在EventBus中使用索引可以提升app效率。使用索引的配置上面已经介绍了,下面介绍一下:

arguments = [ eventBusIndex : 'com.cfox.eventbusdemo.index.EventBusIndex' ]

上面这句是配置生成索引的目录(com.cfox.eventbusdemo.index)和索引类的类名(EventBusIndex), 配置好索引后,重新build一下工程就会生成索引类。

索引为什么能提高app的效率,如果没有使用索引,在注册的时候会通过反射获取类中订阅的事件,使用索引后注册时在索引中查询订阅事件,所以效率会提高很多。

  • 添加使用索引
    配置好索引后,还要将生成的索引添加的项目中,否则索引是不会生效的。索引建议在应用的Application 中添加,如下:

    public class App extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            EventBus.builder().addIndex(new EventBusIndex()).installDefaultEventBus();
        }
    }
    

如果在项目中使用EventBus.getDefault()方法使用EventBus,在使用索引的时候一定要使用installDefaultEventBus()方法添加索引。

有的文章中使用build()方法添加索引,如下方法:

public class App extends Application {
    private EventBus mEventBus;
    @Override
    public void onCreate() {
        super.onCreate();
        mEventBus = EventBus.builder().addIndex(new EventBusIndex()).build();
    }

    public  EventBus getEventBus() {
        return mEventBus;
    }
}

注意:如果使用这种方式添加索引一定要使用build()返回的EventBus实例, 如果使用EventBus.getDefault()方法使用EventBus,索引将不会生效。

stick 事件

  • stick 事件?
    stick 事件就是如果某个对象的stick 事件被发布后,该对象的stick订阅事件没有注册到EvnetBus上,当该对象的stick订阅事件注册到EventBus上时, 该对象的订阅事件将立即被执行。

  • 如何订阅stick 事件
    在订阅事件时将sticky设置为 truesticky = true

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void subMessageOne(MessageObjectOne msgOne) {
        Log.d(TAG, "subMessageOne: " + msgOne.getInfo());
    }
    
  • 发布stick 事件

    MessageObjectOne object = new MessageObjectOne();
    object.setInfo("hello world");
    EventBus.getDefault().postSticky(object);
    

深入一点

上面介绍了比较简单的是使用,EventBus 使用是比较灵活的,下面以使用节点进一步讲解。

  • 注册
    官方文档中的示例如下:

    @Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }
     
    @Override
    public void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }
    

    重官方给出的示例中是在onStartonStop中进行注册和注销, 其实这只是其中的一个使用场景, 不必纠结在什么地方注册和注销,了解原理根据需求灵活使用。

    注册的是什么?
    从注册方式中可以看到register方法中传入的是一个对象。通过查看源码知道,注册时通过反射获取到订阅的事件(如果使用索引,从索引类中获取),也就是说,任何对象只要对象中订阅了事件,就会把订阅的事件注册到EventBus中。

    如下示例:将一个普通对象注册到EventBus 中

    public class EventHandler {
        private static final String TAG = "EventHandler";
    
        @Subscribe
        public void text(MessageObject object) {
            Log.d(TAG, "text: " + object.getInfo());
        }
    }
    
    EventHandler mHandler = new EventHandler(); 
    EventBus.getDefault().register(mHandler); // 注册
    EventBus.getDefault().unregister(mHandler); // 注销
    

    注册后,如果发布这个类型的消息,这个类中订阅的事件就会响应。不用的时候注销一下就可以了。

  • 订阅事件
    在EventBus3.0中订阅事件使用注解@Subscribe,所以可以随意命名。事件参数必须只有一个参数。

    不同消息的订阅
    EventBus是根据事件消息参数的类型进行分发相响应的,也就是说,post一种类型的消息,只有订阅相同消息的订阅事件才能响应。如下订阅事件代码示例:

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void subMessageOne(MessageObjectOne msgOne) {
        Log.d(TAG, "subMessageOne: " + msgOne.getInfo());
    }
    
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void subMessageTwo(MessageObjectTwo msgTwo) {
        Log.d(TAG, "subMessageTwo: " + msgTwo.getInfo());
    }
    

    使用下面方式发送消息将只有subMessageOne订阅事件得到响应

    MessageObjectOne object = new MessageObjectOne();
    object.setInfo("hello world");
    EventBus.getDefault().post(object);
    

推荐阅读更多精彩内容

  • 项目到了一定阶段会出现一种甜蜜的负担:业务的不断发展与人员的流动性越来越大,代码维护与测试回归流程越来越繁琐。这个...
    fdacc6a1e764阅读 2,245评论 0 4
  • 对于Android开发老司机来说肯定不会陌生,它是一个基于观察者模式的事件发布/订阅框架,开发者可以通过极少的代码...
    飞扬小米阅读 959评论 0 51
  • “Some Interesting Open Source Projects of Android”这个系列主要是...
    Burjal阅读 1,823评论 2 10
  • 文章基于EventBus 3.0讲解。首先对于EventBus的使用上,大多数人还是比较熟悉的。如果你还每次烦于使...
    Hohohong阅读 890评论 0 5
  • 先吐槽一下博客园的MarkDown编辑器,推出的时候还很高兴博客园支持MarkDown了,试用了下发现支持不完善就...
    Ten_Minutes阅读 298评论 0 2