EventBus详解

1.前言

EventBus是一款针对Android优化的发布/订阅事件总线。可以替代广播、startActivityForResult、Handler、异步回调等来实现各组件间、组件与后台线程间的通信。它的优点是开销小,代码更优雅,以及将发送者和接收者解耦。

通常我们在使用EventBus的时候都是直接需要接收通信的Activity/Fragment中通过EventBus.getDefault().register(this)订阅事件,在需要发起通信的逻辑直接调用EventBus.getDefault().post(Object event)来发布事件。但是要是一个项目中有很多地方都使用EventBus来通信,比如重新登录后更新各个页面的登录状态,或者是接收到通知更新消息提示等,都这样直接使用的话代码重复率很高,并且呢,如果以后升级或者更换EventBus时,各个地方都要修改,这就比较麻烦了。因此我一般是将EventBus的发布和订阅封装到BaseActivity/BaseFragment中。

gitHub地址

2.概述

2.1添加依赖

implementation 'org.greenrobot:eventbus:3.1.1'

2.2三要素

  • Event 事件。它可以是任意类型。
  • Subscriber 事件订阅者。在EventBus3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
  • Publisher 事件的发布者。我们可以在任意线程里发布事件,一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。

2.3 四种线程模型

EventBus3.0有四种线程模型,分别是:

  • POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程。
  • MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
  • BACKGROUND 表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
  • ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。

3.基本实用

3.1定义事件

public class EventMessage<T> {
    private int code;//消息类型
    private T data;//消息数据

    public EventMessage(int code,T data){
        this.code=code;
        this.data=data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

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

    @Override
    public String toString() {
        return "EventMessage{" +
                "code=" + code +
                ", data=" + data +
                '}';
    }
}

 

3.2注册事件

@Override
protected void onCreate(Bundle savedInstanceState) {           
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     EventBus.getDefault().register(this);
}

 

 

3.2解除注册

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

 

3.3发送事件

//普通事件
EventBus.getDefault().post(event);

//粘性事件
EventBus.getDefault().postSticky(event);

 

3.4处理事件

//普通事件处理
@Subscribe(threadMode = ThreadMode.MAIN)
public void onReceiveEvent(EventMessage msg){
//处理事件
}

//粘性事件处理
@Subscribe(threadMode = ThreadMode.MAIN,sticky=true)
public void onReceiveStickyEvent(EventMessage msg){
//事件处理
}

4.封装

事件EventMessage:

public class EventMessage<T> {
    private int code;//消息类型
    private T data;//消息数据

    public EventMessage(int code,T data){
        this.code=code;
        this.data=data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

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

    @Override
    public String toString() {
        return "EventMessage{" +
                "code=" + code +
                ", data=" + data +
                '}';
    }
}

 

事件类型:EventCode:

/**
 * 消息类型
 */
public class EventCode {
    //根据具体业务定义类型
    public static final int EVENT_A=1000;
    public static final int EVENT_B=1001;
    public static final int EVENT_C=1002;
    public static final int EVENT_D=1003;
    public static final int EVENT_E=1004;
}

 

EventBus封装:

public class EventBusUtils {
    private EventBusUtils(){

    }

    /**
     * 注册EventBus
     * @param subscribver
     */
    public static void register(Object subscribver){
        EventBus eventBus=EventBus.getDefault();
        if(!eventBus.isRegistered(subscribver)){
            eventBus.register(subscribver);
        }
    }


    /**
     * 解除注册EventBus
     * @param subscriber
     */
    public static void unregister(Object subscriber){
        EventBus eventBus=EventBus.getDefault();
        if(eventBus.isRegistered(subscriber)){
            eventBus.unregister(subscriber);
        }
    }

    /**
     * 发送普通事件消息
     */
    public static void post(Object event){
        EventBus.getDefault().post(event);
    }

    /**
     * 发送粘性事件消息
     */
    public static void postSticky(Object event){
        EventBus.getDefault().postSticky(event);
    }
/**
     * 移除所有的粘性订阅事件
     */
    public static void removeAllStickyEvents(){
        EventBus.getDefault().removeAllStickyEvents();
    }
}

 

案例:从MainActivity分别跳转FirstActivity和SecondActivity,跳转SecondActivity时发送粘性事件,返回到MainActivity时发送普通事件

 

代码实战:

BaseActivity:

public abstract class BaseActivity extends AppCompatActivity {

    private String TAG="BaseActivity";
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutResId());
        initView();
        initData();

        if(isRegisteredEventBus()){//放到initView后面  防止 接收到event事件需要更新UI的时候 布局还未初始化完成
            EventBusUtils.register(this);
        }

    }

    @Override
    protected void onDestroy() {
        release();
        if(isRegisteredEventBus()){
            EventBusUtils.unregister(this);
        }
        super.onDestroy();
    }

    /**
     * 获取布局
     * @return 布局ID
     */
    protected abstract int getLayoutResId();

    /**
     * 初始化视图
     */
    protected void initView(){}

    /**
     * 初始化数据
     */
    protected void initData(){}

    /**
     * 释放资源
     */
    protected void release(){}



    /**
     * 是否注册事件分发
     * @return true:注册    false:不注册 默认不注册
     */
    protected boolean isRegisteredEventBus(){
        Log.e(TAG, "isRegisteredEventBus: 00000");
        return false;
    }

}

MainActivity:

public class MainActivity extends BaseActivity implements View.OnClickListener {

    private String TAG="MainActivity";
    private TextView tv;
    private Button bt1,bt2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initView() {
        super.initView();
        tv=findViewById(R.id.tv);
        bt1=findViewById(R.id.bt1);
        bt2=findViewById(R.id.bt2);
        bt1.setOnClickListener(this);
        bt2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {


        switch (v.getId()){
            case R.id.bt1:
                FirstActivity.startActivity(MainActivity.this);
                break;
            case R.id.bt2:
                EventMessage eventMessage=new EventMessage(EventCode.EVENT_E,"来自mainactivity的msg");
                EventBusUtils.postSticky(eventMessage);
                SecondActivity.startActivity(MainActivity.this);
                break;
        }
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void  onReceiveEvent(EventMessage msg){
        String m=(String) msg.getData();
        if(msg.getCode()==EventCode.EVENT_A){
            tv.setText(m);
        }else if(msg.getCode()==EventCode.EVENT_B){
            tv.setText(m);
        }
    }

    @Override
    protected boolean isRegisteredEventBus() {
        Log.e(TAG, "isRegisteredEventBus: 1111" );
        return true;
    }
}

FirstActivity:

public class FirstActivity extends BaseActivity implements View.OnClickListener {
    private String TAG="FirstActivity";
    private TextView tv;
    private Button bt;

    /**
     * 启动activity
     */
    public static void startActivity(Activity srcActivity) {
        Intent intent=new Intent(srcActivity,FirstActivity.class);
        srcActivity.startActivity(intent);
    }
    @Override
    protected int getLayoutResId() {
        return R.layout.activity_first;
    }

    @Override
    protected void initView() {
        super.initView();
        tv=findViewById(R.id.tv);
        bt=findViewById(R.id.bt1);
        bt.setOnClickListener(this);
    }

    @Override
    protected void initData() {
        super.initData();
    }
    
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt1:
                EventMessage msg=new EventMessage(EventCode.EVENT_A,"来自firstactivity的消息");
                EventBusUtils.post(msg);
                this.finish();
                break;
        }
    }
}

SecondActivity:

public class SecondActivity extends BaseActivity implements View.OnClickListener {
    private String TAG="SecondActivity";
    private TextView tv;
    private Button bt;
    public static void startActivity(Activity activity){
        Intent intent=new Intent(activity,SecondActivity.class);
        activity.startActivity(intent);

    }


    @Override
    protected int getLayoutResId() {
        return R.layout.activity_second;
    }

    @Override
    protected void initView() {
        super.initView();
        tv=findViewById(R.id.tv);
        bt=findViewById(R.id.bt1);
        bt.setOnClickListener(this);
    }

    @Override
    protected void initData() {
        super.initData();
    }

    @Override
    protected boolean isRegisteredEventBus() {
        return true;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt1:
                EventMessage msg=new EventMessage(EventCode.EVENT_B,"来自secondactivity的消息");
                EventBusUtils.post(msg);
                this.finish();
                break;
        }
    }
    @Subscribe(threadMode = ThreadMode.MAIN,sticky=true)
    public void onReceiveEvent(EventMessage msg){
        Log.e(TAG, "onReceiveEvent: msg:"+msg.toString() );
        if (msg.getCode()==EventCode.EVENT_E){
            tv.setText((String)msg.getData());
        }
    }
}

 

5.注意

1.在基类中封装时,注意注册EventBus放到初始化视图后面,防止收到粘性事件需要更新UI时 布局还未初始化玩  会报空指针异常

 

6.参考

EventBus的优雅封装

 

posted @ 2018-12-20 15:04  段合江  阅读(1549)  评论(0编辑  收藏  举报