写给同事的EventBus使用指南(二)

尊重他人的劳动成果,转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/52209876, 本文出自:【gengqiquan的博客】

写给同事的EventBus使用指南(一) 里面介绍了EventBus的简单用法。这篇我们讲EventBus的线程切换和响应优先级设置以及粘性事件。
EventBus的强大当然不仅仅是替代下广播和 startActivityForResult, EventBus还提供了线程切换以及注册方法的相应顺序设置
先来看线程切换,怎么设置?
写给同事的EventBus使用指南(二)_第1张图片

如上图,通过在注解里面指定threadMode,我们可以看到有四种线程模式,咱从下往上看。】

POSTING
这是EventBus的默认模式,在发送者的线程执行注解方法,就是在调用了 EventBus.getDefault().post(new CommentChangeEvent());的线程执行。不论该线程是否为主线程(UI 线程)。当发送者线程为主线程时,响应方法中不能有耗时操作,会阻塞主线程

BACKGROUND
在后台线程中执行响应方法。如果发送者的线程不是主线程,直接调用注册方法,否则启动唯一的后台线程去处理。由于后台线程是唯一的,当事件超过一个的时候,它们会被放在队列中依次执行,所以这类的注册方法最好不要有重度耗时的操作或太频繁的轻度耗时操作,以免造成其他操作等待

MAIN
在主线程中执行注册方法。如果发送者线程就是主线程,则直接调用注册方法,否则通过主线程的 Handler 发送消息到主线程中处理注册方法。

ASYNC
使用一个空闲线程来处理。和BACKGROUND不同的是,ASYNC的所有线程是相互独立的,因此不会出现卡线程的问题。

优先级设置,怎么设置?

 @Subscribe(threadMode = ThreadMode.BACKGROUND,priority = 100)
    public void onEvent(CommentChangeEvent event) {

    }

通过指定priority 值,这是一个int型的参数,值越大优先级越高,比如你同时注册了两个参数为CommentChangeEvent 的方法,一个priority 值为100,一个为50,当 调用 EventBus.getDefault().post(new CommentChangeEvent());时,priority 值为100的注册方法先会被通知到,从而优先执行。既然有了优先级,那么可不可以当一个优先级高的注册方法接收到事件后不让后面的优先级低的接收呢?当然可以,我们可以调用 EventBus.getDefault().cancelEventDelivery(CommentChangeEvent.class);来截断事件的传递。这样事件就不会继续通知下面的注册方法了。

粘性事件StickyEvent
什么叫粘性事件?一个事件发送了后,如果不主动移除,会一直存在,之后再有声明为粘性事件的方法去注册的时候,会去队列中寻找是不是有同样参数的粘性事件已经发送并且存在,有则执行该注册的方法。

场景举例:我们有一个商品界面,一个activity,里面通过viewpager放了四个fragment。我们在activity里面需要进行商品的关注,拨打商家电话,这样我们就需要商品的详情信息。而我们的四个fragment里面也需要通过商品的详情的字段进行一些请求,比如商品名称去搜索类似商品,有人可能就说了,让服务端改接口啊!你去说试试。这里我们就不得不请求五次商品基础信息的接口了。如果恰恰你接口不能支持缓存。呵呵!由于请求基础数据的响应时间不可知,这里我们就没办法先请求完数据然后通过setArguments传递数据。同时我们也不知道fragment是不一定会在数据请求好之前加载好,这样就不能用之前的EventBus.getDefault().post(new CommentChangeEvent());来传递数据。当然,可以强制延迟数据加载。不过延迟多少呢?体验肯定不好吧。这里我们就可以用粘性事件来解决这个问题。
我们在四个fragment里注册粘性事件

 @Subscribe(threadMode = ThreadMode.BACKGROUND,priority = 100,sticky = true)
    public void onEvent(CommentChangeEvent event) {

    }

通过指定sticky = true,默认为false。
然后在activity里接收到网络数据返回后调用

EventBus.getDefault().postSticky(new CommentChangeEvent());

把请求的商品基础信息数据发送过去。由于发送的粘性事件是会被 EventBus保存在静态队列里的,当我们注册粘性方法的时候我们会先去队列里找有没有相同参数的这个事件。同样发送的时候也会去找有没有注册这个粘性事件的方法。这样不管数据请求和fragment哪个先成功,都可以接收到数据。
怎么样?瞬间五个请求变成一个,不过这里需要注意,粘性事件是会一直存在静态队列里的,下次你点另外一个商品进来的话会发现数据先还是之前的商品数据,然后会再改变成现在商品的数据。解决的办法就是我们在activity销毁的时候移除这个粘性事件,通过调用 EventBus.getDefault().removeStickyEvent(new CommentChangeEvent());移除粘性事件。

好了,关于EventBus的使用方法就讲到这里了,有什么疑问或者建议请留言指出。

我建了一个QQ群(群号:121606151),用于大家讨论交流Android技术问题,有兴趣的可以加下,大家一起进步。

你可能感兴趣的:(android)