EventBus的使用

EventBus是一个Android平台上的事件发送/订阅框架,采用观察者模式实现,可以优化组件间的信息传递过程。

这篇笔记主要参考官方文档,点[这里][1].
[1]: https://github.com/greenrobot/EventBus/blob/master/HOWTO.md

基本的使用

1. 定义events

Events通常是一个POJO(plain old Java object).可以根据需要,随便定义。可以定义多种类型的events,事件处理函数根据事件的类型实现重载。events除了自定义,还可以是Java中的基本类型(int, boolean等)。

public class MessageEvent{
    public String message;
    
    public MessageEvent(String message){
        this.message = message;
    }
}

2. 注册订阅者

只有需要接收events的地方,才需要注册订阅者。只是发送事件的话,不必注册。
在Acitvity中注册和注销订阅者:

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

    @Override
    public void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }

3. 添加events处理函数

其实添加events处理函数也是注册订阅者的一部分,它们俩一起完成了注册任务。
在注册了订阅者的地方,添加事件处理函数。

    // This method will be called when a MessageEvent is posted
    public void onEvent(MessageEvent event){
        Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
    }

    // This method will be called when a SomeOtherEvent is posted
    public void onEvent(SomeOtherEvent event){
        doSomethingWith(event);
    }

有两点需要注意:

  1. 事件处理函数必须有参数,且只能有一个参数。函数根据这个参数的类型,实现重载的功能。
  2. 事件处理函数的名字必须以onEvent开头,且必须是以下四种:
    • onEvent
    • onEventMainThread
    • onEventBackgroundThread
    • onEventAsync

4. 发送events

可以在任何地方发送一个事件。所有注册了这个事件类型的订阅者都可以收到它。

EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

这里有两点需要注意:

  • 如果event是基本类型,发送时event会被自动装箱。因此事件处理函数(onEvent)的参数类型必须是基本类型对应的对象类型。
  • 所有注册了event对象的父类的订阅者,都可以收到这个event。也就是说,如果某个订阅者的某个事件处理函数的参数是Object类型

onEvent(Object object)

那么所有发出去的event,它都可以收到。

线程模型

EventBus可以自动处理线程问题,使我们从后台线程与UI线程的切换中解放出来。

在EventBus中,通过约定事件处理函数名称的方式,决定在哪个线程中执行事件处理方法。

  • onEvent
    对应PostThread模型,事件处理函数将会在事件发送者的线程上执行。这种模式,不需要切换线程,是最快速的,推荐默认采用。
  • onEventMainThread
    对应MainThread模型,事件处理函数将会在主线程上执行。
  • onEventBackgroundThread
    对应BackgroundThread模型,如果发送线程不是主线程,那么事件处理函数将会直接在发送线程调用。如果发送线程是主线程,那么EventBus会启用一个后台线程执行事件处理函数。
  • onEventAsync
    对应Async模型,EventBus会启用一个单独的线程(既不是发送线程,又不是主线程)执行事件处理函数。EventBus会使用线程池,重用线程。

设定优先级

可以在注册的时候,设置订阅者的优先级。

    int priority = 1;  
    EventBus.getDefault().register(this, priority);

高优先级的订阅者,可以先接收到事件。默认的优先级是0.
这里有一点需要注意,用官方文档的话说就是:

Note: the priority does NOT affect the order of delivery among subscribers with different ThreadModes!

也就是说,两个订阅者:subscribe1和subscribe2,subscribe1的优先级较高,那么subscribe1的onEvent函数肯定比subscribe2的onEvent函数先接收到事件,onEventBackgroundThread函数也肯定比subscribe2的onEventBackgroundThread优先。但是不能比较subscribe1的onEvent和subscribe2的onEventBackgroundThread,因为它们的线程模型不同,可能在不同的线程上。

取消events的传递

高优先级的订阅者可以在事件处理函数中取消事件的传递。

    // Called in the same thread (default)
    public void onEvent(MessageEvent event){
        // Process the event 
        ...

        EventBus.getDefault().cancelEventDelivery(event) ;
    }

Sticky Events

Sticky Events可以用于需要延迟接收事件的情况。
普通的事件发送出去以后,EventBus便不再持有了,因此后续注册的订阅者无法接收到它。但是sticky事件不同,EventBus会在内存中为每一种事件类型保存一个最新发送的事件,直到后续发送新的sticky事件,把它覆盖掉。因此后续注册的订阅者,依然可以从内存中得到这个已发送的sticky事件。
发送sticky事件:

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));

注册sticky订阅者:

    @Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().registerSticky(this);
    }

    public void onEventMainThread(MessageEvent event) {
        textField.setText(event.message);
    }

    @Override
    public void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }

也可以直接直接获得某个类型的sticky事件:

EventBus.getDefault().getStickyEvent(Class<?> eventType)

有两点需要注意:

  • sticky类型的订阅者,依然可以收到普通类型的event;但是普通类型的订阅者收不到sticky类型的event
  • 某个类型,只有最新的事件才会被保存
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容