安卓开发之EventBus使用

学完GreenDao之后再来学习下EventBus的使用,EventBus 是一个Android事件发布/订阅框架,它利用发布/订阅者者模式来对项目进行解耦,可以利用很少的代码,来实现多组件间通信/Android的组件间通信。

之前我们学习过一些传统的事件传递方式例如Handler、BroadcastReceiver等,相比之下EventBus代码简洁,使用简单,并将事件发布和订阅充分解耦。BroadcastReceiver常用于那些要与Android系统打交道的事件例如网络、电量的变化等;在BroadcastReceiver的 onReceive方法中可以获得Context 、intent参数,可以调用许多的sdk中的方法,EventBus就比较困难了。Handler一般用于线程间通信,它在发生问题时可以非常明确、快速的进行定位,通过msg.what就可以理清每一条消息流的逻辑,但是其内部类和其定义类是绑定的,造成了事件发布者和接受者之间的高耦合。EventBus的优势在于不像BroadcastReceiver那样依赖于 Context,也解除了Handler所带来的耦合,当然也同样有缺陷,当事件发布遭到大量滥用时,很难从事件发布者开始理清消息流,无法快速的找出是哪个订阅者接受并处理了消息导致的问题。不过凡事有利就有弊,这次就来学习一下EventBus的相关使用。

Event工作模式图如下图所示:
在这里插入图片描述
图中涉及到了三个角色:

  • Event:事件,它可以是任意类型,EventBus会根据事件类型进行全局的通知。事件分为一般事件和Sticky事件,相对于一般事件,Sticky事件不同之处在于,当事件发布后,再有订阅者开始订阅该类型事件,依然能收到该类型事件的最近一个Sticky事件。
  • Subscriber:事件订阅者,当有发布者发布这类事件后,EventBus会执行订阅者的onEven响应函数。订阅者通过register接口订阅某个事件类型,unregister接口退订。
  • Publisher:事件发布者,可以在任意线程里发布事件。一般情况下,使用EventBus.getDefault()就可以得到一个EventBus单例对象,然后再调用post(Object)方法即可。

简单来说,Publisher(事件发布者)通过post()方法,把Event事件发布出去,Subscriber(事件订阅者)在onEvent()方法中接收事件。

那么我们就按照上述的说法来写个小Demo,这里为了简便,Subscriber与Publisher在同一Activity内:

定义事件1:EventSuccess,这里就自定义事件类

public class EventSuccess {
    private int type;
    private String message;
    public EventSuccess(int type, String message) {
        this.type = type;
        this.message = message;
    }
    @Override
    public String toString() {
        return "type= "+type+" message= "+message;
    }
    public int getType() {
        return type;
    }
    public void setType(int type) {
        this.type = type;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

定义事件2:EventFailed

public class EventFailed {
}

MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button success,fail;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EventBus.getDefault().register(this);//在需要订阅事件的模块中,注册eventbus,不能重复注册;EventBus.getDefault得到单例
        setContentView(R.layout.activity_main);
        success = findViewById(R.id.success);
        fail = findViewById(R.id.fail);
        success.setOnClickListener(this);
        fail.setOnClickListener(this);
        textView = findViewById(R.id.textview);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);//不用的时候一定要unregister
    }

    @Override
    public void onClick(View v) {
        //发送事件
        switch (v.getId()){
            case R.id.success:
                EventSuccess event = new EventSuccess(1,"success");
                EventBus.getDefault().post(event);
                break;
            case R.id.fail:
                EventBus.getDefault().post(new EventFailed());
                break;
        }
    }
    
    //事件订阅者 处理事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onSuccessEvent(EventSuccess event) {
        textView.setText(event.toString());
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onFailEvent(EventFailed event) {
        textView.setText("Fail!");
    }
}

效果如下:
点击success:
在这里插入图片描述
点击fail:
在这里插入图片描述

这里说下@Subscribe参数,它其实可接收三个参数,ThreadMode、boolean sticky(也就是是不是sticky事件)、int priority(优先级)。参考EventBus 使用(全面分析,细节提醒)

  • ThreadMode 是用来决定onReceiveMsg将在哪种线程环境下被调用,共有5种Thread mode:

    • POSTING :EventBus的默认模式,表示post事件是什么线程,onReceiveMsg接收事件方法就在同样的线程环境中执行代码
    • MAIN:无论事件发布在什么线程,事件接收都在主线程中执行,这里分为两种情况:
      (1) 事件发布者post事件在主线程,会阻塞post事件所在的线程。也就是如果连续post多个事件,当接收事件方法执行完才能post下
      一个事件。
      (2)事件发布者post事件不在主线程,那么这种情况下是非阻塞的。连续post多个事件,在主线程接收事件是耗时操作的话,执行的
      流程会是非阻塞的。
    • MAIN_ORDERED:无论事件发布者post在什么线程环境,它的执行流程是都非阻塞的,和MAIN模式下,post环境不是主线程的执行流程一样
    • BACKGROUND:该模式下的时间发布者post线程环境与事件接收onReceiveMsg方法的线程环境关系如下:
      (1)post发布环境是主线程的话,事件接收处理的环境是一个子线程。
      (2)post发布环境是子线程的话,事件接收处理环境和post发布环境一样。
    • ASYNC:该模式表示,无论post环境是什么线程,事件接收处理环境都是子线程。
  • sticky:一个boolean型的参数,默认值是false,表示不启用sticky特性。不同于之前的EventBus普通事件传递,sticky可以先post事件,后对订阅者注册。
    接着上面的那个Demo:我们新增发布、注册按钮两个按钮,新增一个空的EventTest自定义事件类,并先将注册函数注释掉:
    在这里插入图片描述
    然后编写按钮点击逻辑:
    在这里插入图片描述
    可以看到这里就改成了postSticky,可以先发布事件,再注册:
    在这里插入图片描述
    效果如下:先点击发布按钮,再点击注册按钮

在这里插入图片描述

  • priority:int型,默认值是0,代表优先级。当post事件发布,onEvent事件接收处理这两者的线程环境相同时,priority值越高,越先接收到事件post事件发布。

猜你喜欢

转载自blog.csdn.net/weixin_42011443/article/details/108433220