EventBus

事件总线.以观察者模式实现,消息推送/订阅.用于Android组件之间相互通信

项目地址:https://github.com/greenrobot/EventBus Docment:http://greenrobot.org/eventbus/documentation/how-to-get-started/

是什么?有什么用?解决了什么问题?

有点类似于广播,可以这样去理解.方便组件之间相互通信,Activity,Service,Fragment...通信这个词有点过于官方,通俗点的说就是在他们之间发消息,传输数据.例如,你在个人主页编辑头像的界面修改了头像,这时候其它页面的头像也需要去修改,这时候可以试试EventBus.

怎么用?

  • 添加依赖
  • 使用三歩曲:
    • 定义事件类
    • 注册事件
    • 发送事件

添加依赖

    compile 'org.greenrobot:eventbus:3.0.0'

使用三步曲:

1,定义事件类

    public static class MessageEvent { 
        /* Additional fields if needed */ 
    }

2.注册事件

  • 注册本组件的EventBus:EventBus.getDefault().register(this);
  • 添加@Subscribe注解:在函数上添加,表示这个函数是接收消息的回调的函数,函数名是自定义的
  • 注销本组件的EventBus:EventBus.getDefault().unregister(this);

Note:一个事件是可以有多个接收者(订阅者),这里只是写一个做为示例

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

    //加上Subscribe注解,这个方法会在事件发出后收到回调,方法名是自定义的
    @Subscribe
    public void onMessageEvent(MessageEvent event) {
        Log.i(TAG, "onMessageEvent: ");
    }

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

3.发送事件

这个方法可以写在View的点击事件上,也可以写在网络请求的回调中...任何你想要的地方

    EventBus.getDefault().post(new MessageEvent());

这时候在回来看这张大图,点击图片查看

这里顺便吐槽下官方示例代码:

如果你打算把注册写在onStart中,请在前面加上判断

    @Override
    public void onStart() {
        super.onStart();
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
    }

上面是EventBus的基本使用流程,其实这才开始:

  • 在事件中传递数据
  • 指定事件接收线程
  • 发送黏性事件Sticky Events
  • 接收事件的优先级别
  • 中止事件传递
  • 订阅者索引

传递数据

不过,上面只是发了一个空的消息,没有传递任何的数据,怎么做呢? 比如:我修改了用户的头像,上传到服务器,服务器返回一个Url,这时候我希望其它界面的头像也更改,这时候我要把这个url传到其它界面:

1.只需要去修改定义事件类中的构造函数,增加一个参数,在加上set和get方法,如下:

    public class UpdateHeadPicEvent {

        private String mUrl;

        public UpdateHeadPicEvent(String url) {
            this.mUrl = url;
        }

        public String getUrl() {
            return mUrl;
        }

        public void setUrl(String url) {
            mUrl = url;
        }
    }

2.在发送事件的地方,使用这个带参的构造去创建对象:

    EventBus.getDefault().post(new UpdateHeadImgEvent(url));

3.在接收消息的回调中用get方法去获取

    @Subscribe
    public void onUpdateHeadPicEvent(UpdateHeadPicEvent event) {
        String url = event.getUrl();
        Log.i(TAG, "onUpdateHeadPicEvent: " + url);
    }

Note:这里只是用了一个String的Url做参考,可以传递的数据还有很多,List集合,Bean对象...

指定事件接收的线程

前面说了加上@Subscribe注解,这个函数在消息推送之后会被回调,其实这个注解还有几个属性,其中threadMode能为这个函数指定线程,如果不写,也会有个默认值:ThreadMode.POSTING,意思是和发送事件所在线程一样

    @Subscribe(threadMode = ThreadMode.POSTING)
    public void onUpdateHeadPicEvent(UpdateHeadPicEvent event) {
        String url = event.getUrl();
        Log.i(TAG, "onUpdateHeadPicEvent: " + url);
    }

ThreadMode列表

  • ThreadMode.POSTING:和发送事件在同一个线程
  • ThreadMode.MAIN:主线程
  • ThreadMode.BACKGROUND:子线程
  • ThreadMode.ASYNC:异步线程

发送黏性事件Sticky Events

上面示例代码所说的情况是:当发送消息推送者推送消息的时候,订阅者会立马收到消息,它会把消息推送给它所有的订阅者.注意后面这句话:如果你想在消息推送完成之后,让新加入的订阅者也能收到这条消息,这时候你可以试试Sticky Events,这个事件就像一个常驻广播,只要是有新的订阅者订阅了这个事件,就会收到消息.当然,有两点要求:

  1. 首先,发送的是黏性事件,代码将post改为postSticky
//                EventBus.getDefault().post(new MessageEvent());
                EventBus.getDefault().postSticky(new MessageEvent());
  1. 然后,订阅者要声明自己能够接收到黏性事件的消息:代码中@Subscribe注解中的sticky值为true,满足了这两点,就能愉快的玩耍了.

     @Override
     protected void onStart() {
         super.onStart();
         if (!EventBus.getDefault().isRegistered(this)) {
             EventBus.getDefault().register(this);
         }
     }
    
     @Subscribe(sticky = true)
     public void onMessageEvent(LoginEvent event) {
         Log.i(TAG, "onMessageEvent: 我是sticky event 收到消息");
     }
    
     @Override
     protected void onDestroy() {
         super.onDestroy();
         EventBus.getDefault().unregister(this);
     }
    

测试Log日志

接收事件的优先级别

EventBus可以定义接收事件方的优先级别,在@Subscribe注解中有一个priority的参数,默认值是0,可以自行配置1.2.3.4...数值越大优先级越低,会越晚收到消息

    @Subscribe(priority = 0)
    public void onUpdateHeadPicEvent(UpdateHeadPicEvent event) {
        String url = event.getUrl();
        Log.i(TAG, "onUpdateHeadPicEvent: " + url);
    }

中止事件传递

类似于有序广播,优先级高的订阅者,可以终止事件向下传递,EventBus也提供了此功能

    @Subscribe(priority = 0)
    public void onUpdateHeadPicEvent(UpdateHeadPicEvent event) {
        EventBus.getDefault().cancelEventDelivery(event) ;
    }

订阅者索引

这个新特性是在EventBus 3.0推出,简单的说:利用annotationProcessor去生成一个关于订阅者的索引类,保存订阅者的相关信息. 有什么用?提高效率,注册从运行时的反射,转移到了编译时 怎么用?两种方式:

  • 在gradle版本2.2.0以前使用:Android-apt
  • 在gradle版本2.2.0以上使用:annotationProcessor

这里说annotationProcessor的方式,现在新建项目一般都在2.2.0以上: 添加好Gradle设置之后,重新build项目,就会为你生成这样的类:MyEventBusIndex

用法:将它配置应用于默认的EventBus,调用下面代码:可放在Application的onCreate中调用

    EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();

未添加前和添加后我分别做了三次测试,注册完成的时间对比,速度快了不止一倍,这还是只有两个订阅者的时候,如果订阅订阅者更多呢,

    //未添加前
    I/Subscriber1Activity: onMessageEvent: register start 1491892487664
    I/Subscriber1Activity: onMessageEvent: register end 1491892487666
    I/Subscriber1Activity: onMessageEvent: register start 1491892568177
    I/Subscriber1Activity: onMessageEvent: register end 1491892568180
    I/Subscriber1Activity: onMessageEvent: register start 1491892715342
    I/Subscriber1Activity: onMessageEvent: register end 1491892715344

    //添加后
    I/Subscriber1Activity: onMessageEvent: register start 1491892648185
    I/Subscriber1Activity: onMessageEvent: register end 1491892648186
    I/Subscriber1Activity: onMessageEvent: register start 1491892814517
    I/Subscriber1Activity: onMessageEvent: register end 1491892814518
    I/Subscriber1Activity: onMessageEvent: register start 1491892868879
    I/Subscriber1Activity: onMessageEvent: register end 1491892868880
在Lib的model中使用:

build.gradle也要添加上图中同样的参数,在上图中,这个参数是自定义的,不同的model可以为他生成不同的索引类:

    arguments = [eventBusIndex: 'com.example.myapp.MyEventBusIndex']

更改默认配置也需要多添加一行代码:

    EventBus eventBus = EventBus.builder()
        .addIndex(new MyEventBusAppIndex())
        .addIndex(new MyEventBusLibIndex())
        .installDefaultEventBus();

最后代码地址:https://github.com/Shib90/Eventbusdemo

results matching ""

    No results matching ""