Android开发Android开发Android开发经验谈

EventBus使用及解析

2018-10-16  本文已影响112人  奔跑吧李博

在我们刚学Android不久,就会学到用接口回调来异步通知事件。写起来也算顺手,但是接口回调需要不断地设置listener,耦合性较大,当项目越来越复杂,接口回调的传值会形成一张错综复杂的网,有这样使用经历的人就会深有感触。于是,就可以使用EventBus的事件传递方法,在发送着和接收者完全解耦,传递接收范围广,接下来就学习怎样使用Eventbus。

事件产生过程

流程示意图

EventBus的三要素

Event:事件,可以是任意类型的对象。
Subscriber:事件订阅者,在EventBus3.0之前消息处理的方法只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,他们分别代表四种线程模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING)。
Publisher:事件发布者,可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法。可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就好了,根据post函数参数的类型,会自动调用订阅相应类型事件的函数。

使用步骤

引入库

    implementation 'org.greenrobot:eventbus:3.0.0'

这里可以看到EventBus.getDefault()内部调用的是懒汉式的单例获取Eventbus对象方法。

    /** Convenience singleton for apps using a process-wide EventBus instance. */
    public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }

创建发送的实体类,根据发送者的实体类和接收者的实体类相匹配来看是否接收事件。

public class PostMsg {
    private int num;
    private String title;

    public PostMsg(int num, String title) {
        this.num = num;
        this.title = title;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

在任意需要发送事件的地方发送消息,对,发送就是这么简单:

EventBus.getDefault().post(new PostMsg(100,"这里是标题"));

接收消息的地方需要在onCreate()方法中进行注册

        EventBus.getDefault().post(this);

在onDestroy()方法中取消注册(避免内存泄漏)

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

接收消息

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(PostMsg postMsg){
        Toast.makeText(getApplicationContext(),postMsg.getNum() + "  " + postMsg.getTitle(),Toast.LENGTH_LONG).show();
    }

线程模式

public enum ThreadMode {

    POSTING,

    MAIN,

    BACKGROUND,

    ASYNC
}

POSTING:订阅者方法将在发布事件所在的线程中被调用。是默认的线程模式,该模式不会切换线程,意味着最少的性能开销。可能会发生下主线程。
MAIN:订阅者方法将在主线程中被调用。
BACKGROUND:订阅者方法将在后台线程中被调用。如果发布事件的线程不是主线程,那么订阅者方法将直接在该线程中被调用。如果发布事件的线程是主线程,那么将使用一个单独的后台线程
ASYNC:订阅者方法将在一个单独的线程中被调用,该模式可用来执行耗时操作。

粘性事件

当有需求需要发送消息,所有注册过的Activity都能收到。但是此时只有一部分Activity创建了,那么此时发出消息,未创建的Activity就接收不到消息。粘性事件就解决了该问题。通过 postSticky 发送粘性事件,这个事件不会只被消费一次就消失,而是一直存在系统中,直到被 removeStickyEvent 删除掉。

发布粘性事件

EventBus.getDefault().postSticky(new PostMsg(100,"这里是标题"));

接收粘性事件

    @Subscribe(sticky = true)
    public void onEventMainThread(PostMsg postMsg){

    }

移除指定粘性事件

        //移除某种类型粘性事件
        EventBus.getDefault().removeStickyEvent(ThreadMode.xxx);
        //移除某种对象粘性事件
        EventBus.getDefault().removeStickyEvent(object);
         //移除所有粘性事件
        EventBus.getDefault().removeAllStickyEvents();
上一篇下一篇

猜你喜欢

热点阅读