Android 模块通信—— EventBus

    EventBus 是 Android 的一个基于发布/订阅模式的轻量级框架,用于 Android 解耦的事件传递,开源地址

  这是官方地址的一个说明图:


    可以看到,它是通过发布者的 post() 来发送时间,订阅者的 onEvent() 来响应事件,我们来看看怎么使用 EventBus:

    第一步当然是导入它的依赖库:

compile 'org.greenrobot:eventbus:3.1.1'

    首先我们需要注册 EventBus,注册有两种方式,一般使用第一种默认方式。

// 第一种,在 onCreate() 方法中注册
        EventBus.getDefault().register(this);
        // 第二种
        EventBusBuilder busBuilder = EventBus.builder()
                // 设置线程池,默认为动态多线程的线程池
                .executorService(Executors.newSingleThreadExecutor())
                // 事件是否继承,默认 true
                .eventInheritance(true);
        EventBus eventBus = busBuilder.build();
        eventBus.register(this);

    这里的事件是否继承是什么意思呢?如果事件 A 继承自事件 B,当发布者发布事件 A 时,如果可继承为 true,那么订阅者 B 也是可以收到事件 A 的,反之则接收不到。

    我们需要注意的是,我们一定要记得在 onDestroy() 中去取消注册 EventBus:

 @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

    首先我们先来定义一个事件:    

public class Event {
    private String data;

    public Event(String data){
        this.data = data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }
}

然后我们需要发送事件:

// 发送事件
        EventBus.getDefault().post(new Event("响应事件"));

    响应事件:

// 通过注解方式响应事件
    @Subscribe(threadMode = ThreadMode.POSTING,priority = 1,sticky = false)
    public void onEvent(Event event ){
        // 响应事件 
    }

    这里的三个参数是什么意思呢?ThreadMode 是线程模式,我们看它的源码是一个枚举,有五种类型:

类型   说明
POSTING                发布者在哪个线程发布事件,订阅者就在哪个线程响应事件
MAIN     不管发布者在哪个线程发布事件,订阅者都在主线程响应事件。不同的是:当发布者在主线程时,订阅者会直接阻塞线程来响应事件,而当发布者在其它线程时,订阅者就会非阻塞的排队等待响应事件

MAIN-ORDERED                               

不管发布者在哪个线程,订阅者都在主线程响应事件,与 MAIN 不同的是,MAIN-ORDERED 一直都是非阻塞的形式等待响应事件
BACKGROUND如果发布者不在主线程,那么订阅者直接在发布者的线程响应事件,如果发布者在主线程,那么订阅者就会使用一个单独的后台线程按序响应事件
ASYNC 不管发布者在哪个线程,订阅者都是在一个独立的线程里面响应事件,发布者不会等待订阅者的响应,所以这种模式一般用于响应的事件比较耗时的情况

    priority 是优先级,默认为 0,越大优先级越高;sticky 代表是不是粘性事件,默认为 false。 

    然后我们在另一个没有与发布者有任何代码关联的 Activity 来发送一个事件: 

postEvent=findViewById(R.id.btn_post_event);
        postEvent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new Event("响应事件"));
            }
        });

    效果图:


    可以看到我们发送了事件过后,马上就响应了该事件。

    上面我们说了一个黏性事件,这个是什么意思呢?我们来举一个栗子,大家想一下:如果我们发布了一个事件,但是订阅了这个事件的 Activity 还没有启动,那它肯定是不能响应该事件的,我们可以看看,我们在第一个页面发送事件 B,在第二个页面响应事件 B:

// 第一个 Activity 页面发送事件 B
        postEvent=findViewById(R.id.btn_post_event_b);
        postEvent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new EventB("响应事件"));
            }
        });
// 第二个 Activity 页面响应事件 B
    @Subscribe(threadMode = ThreadMode.POSTING)
    public void onEvent(EventB eventB){
        Toast.makeText(SubscriberEventActivity.this,eventB.getData(),Toast.LENGTH_SHORT).show();
    }

    效果图:


    我们可以看到,第二个页面是没有响应事件的,这个时候黏性事件的作用就出来了,黏性事件的作用就是只要是发布者发送了事件,不管当时订阅者有没有接收到这个事件,只要订阅者来订阅这个事件就能接收到这个事件,怎么实现呢?

// 第一个 Activity 页面发送事件 B
        postEvent=findViewById(R.id.btn_post_event_b);
        postEvent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 通过 postSticky() 来发送粘性事件
                EventBus.getDefault().postSticky(new EventB("响应事件B"));
            }
        });
// 第二个 Activity 页面响应事件 B,设置 sticky 为 true
    @Subscribe(threadMode = ThreadMode.POSTING,sticky = true)
    public void onEvent(EventB eventB){
        Toast.makeText(SubscriberEventActivity.this,eventBus.getData(),Toast.LENGTH_SHORT).show();
    }

    效果图:


    可以看到,就算我们当时不能订阅该事件,只要我们后面订阅该事件就能就收到该事件,但是就又出现一个问题了,它会只要重新进一次页面,重新订阅一次就会响应一次事件,那怎么办呢?我们就可以移除黏性事件:

 // 第二个 Activity 页面响应事件 B,设置 sticky 为 true
    @Subscribe(threadMode = ThreadMode.POSTING,sticky = true)
    public void onEvent(EventB eventB){
        Toast.makeText(SubscriberEventActivity.this,eventB.getData(),Toast.LENGTH_SHORT).show();
        // 我们在响应该事件后就移除该黏性事件
        EventBus.getDefault().removeStickyEvent(EventB.class);
    }

    效果图:


    可以看到,我们移除黏性事件过后,就不会再响应该事件了。

    EventBus 的简单使用就是这么多,那么我们使用 EventBus 需要注意什么呢?

    1. EventBus 一般用于模块间通信,如果模块内能够适应 Intent、接口等通信时优先使用 Intent 通信

    2. 因为模块开发一般是协同开发,所以对于事件的定义和响应要避免重复和包含

    3. 因为 EventBus 是解耦的,所以就不要在响应事件里面发布事件来增加耦合性

    4. 因为注册 EventBus 是默认动态多线程的线程池,所以要避免进行一些大量耗时操作的发布

    5. 如果按照顺序处理事件,尽量保证发布者和订阅者在同一种线程,即使用 ThreadMode.POSTING 

    6. 要记得取消注册 EventBus,要不然它对 Activity 的持有会造成内存泄露




  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android EventBus是一个用于Android应用程序内部组件之间通信的开源库。它基于发布/订阅模式,简化了组件之间的通信,使得开发者能够更轻松地实现松耦合的设计。 使用EventBus,你可以定义事件(Event),并将其发布(Post)到EventBus中。其他组件可以订阅(Subscribe)这些事件,并在事件发生时接收通知并执行相应的操作。这种机制使得组件之间的通信更加简单和灵活。 EventBus提供了多种线程模型,可以根据需要选择适合的模式。例如,可以在主线程中订阅事件,以更新UI,或在后台线程中执行耗时操作。 要在Android项目中使用EventBus,你需要首先添加EventBus库的依赖。然后,定义事件类和事件处理方法,并注册和取消注册事件订阅者。最后,在适当的地方发布事件,并在事件处理方法中执行相应的操作。 以下是一个简单的示例: 1. 添加EventBus库的依赖: ```java implementation 'org.greenrobot:eventbus:3.2.0' ``` 2. 定义事件类: ```java public class MessageEvent { private String message; public MessageEvent(String message) { this.message = message; } public String getMessage() { return message; } } ``` 3. 注册和取消注册事件订阅者: ```java @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { super.onStop(); EventBus.getDefault().unregister(this); } ``` 4. 订阅事件和定义事件处理方法: ```java @Subscribe(threadMode = ThreadMode.MAIN)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值