EventBus 这一篇还不够

  • 参考网站
  • 环境配置
  • 原理介绍
  • 入门例子
    • 定义 MessageEvent 对象
    • 定义 处理 MessageEvent对象方法
    • 注册和取消订阅
    • 发布MessageEvent
    • 理清思路
  • ThreadMode 介绍
  • EventBus其他功能介绍
    • StickyEvent
    • 订阅权限 Subscriber Priorities
    • 取消事件分发
    • 还有其他的就自己看官网吧
  • 写在最后的话

参考网站

EventBus 官网

环境配置

Gradle:

compile ‘org.greenrobot:eventbus:3.0.0‘

Maven:

    org.greenrobot
    eventbus
    3.0.0
" data-snippet-id="ext.477182e72475e3c7594ab9761c46f10b" data-snippet-saved="false" data-codota-status="done"><dependency>
    <groupId>org.greenrobot</groupId>
    <artifactId>eventbus</artifactId>
    <version>3.0.0</version>
</dependency>

原理介绍

这张图是比较形象的EventBus的工作原理图,来自EventBus官网。我们可以形象的理解 EventBus 就是一个老司机,他有一个手册,手册上写了路线有很多个餐馆。这个时候有一个乘客上车,掏出手机给老师机看高德地图上的一条路线说我要去这儿,老司机和餐馆老板有私下交易,所以他会拉着你挨个经过这些餐馆。

上面有一些字是加粗的,老司机代表 EventBus,他在系统中是一个单例模式。所有的事件都要经过老司机,EventBus维护这一个HashMap,及一个手册,手册中记录了很多的路线,每条路线上有很多餐馆,路线就是我们的 事件(Message,这里不够形象,但是大概理解吧),好,路线上有很多个餐馆,餐馆就是 订阅者,源码中直接用这样的结构存储 Map<Object, List<Class<?>>>,Object就是事件, List 里面存的订阅者,当某种事件发生时,这条线上的所有订阅者都会收到消息。至于还有一个乘客,发布事件的人,其实就是 EventBus 本身,通过 EventBus.getDefault.post( Message ) 发送事件。

不知你理解了没有,反正我理解了。如果不理解,那就看代码吧!

入门例子

1. 定义 MessageEvent 对象

MessageEvent.java

public class MessageEvent {

    public final String message;

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

2. 定义 处理 MessageEvent对象方法

MainActivity.java

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}

3. 注册和取消订阅

MainActivity.java

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

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

4. 发布MessageEvent

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

理清思路

根据代码,我们再来理解刚开始给的那张图。如果使用EventBus这个老司机,那么系统中就只会出现这么一个老司机,它是单例模式,猜都能猜到,如果不信,你可以跟到源代码EventBus.getDefault()中看,很基本的双重锁写法:

static volatile EventBus defaultInstance;

public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

然后通过 老司机.post(MessageEvent event) 出来的事件首先会传给老司机,因为系统中只有老司机知道有哪些订阅者,并且他们订阅的是什么事件,他是通过注解的形式知道,@Subscribe表示该方法是要处理事件的,但是处理哪种事件呢?后面方法的参数决定 MessageEvent event。当然还不要忘了一定要给老司机 注册他才认识你 EventBus.getDefault().register(this);,看源码发现在在调用register的时候,EventBus才会去找这个类中的 @Subscribe

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}

然后老司机拿到了 事件,并且看了看他的注册表中有哪些家伙订阅了这个事件,当事件发生时,就把事件传给他们,让他们去处理。我觉得这样写应该所有人都能明白吧,至于底层的原理,可以看看EventBus的源码。

ThreadMode 介绍

还记得上面的HelloWorld例子中我们用到了 @Subscribe(threadMode = ThreadMode.MAIN), MAIN 表示UI主线程,EventBus包括以下4种:

  • ThreadMode.POSTING默认模式,效率高,收到消息就执行。让订阅方法工作在与发布消息同一个线程中。
  • ThreadMode.MAIN:让订阅方法始终切换到 UI主线程中执行
  • ThreadMode.BACKGROUND:启动新线程,让订阅方法在新线程中执行
  • ThreadMode.ASYNC:异步模式,也是工作在新线程中,但是EventBus提供了线程池的管理,避免线程不停创建。

其实ThreadMode就是为了让我们更好的在线程中切换,大家都知道Android中UI主线程后后台线程的区别,以前我们都要使用 Handler,AsyncTask 等来处理,代码繁重,现在只需要一个注解就搞定了,是不是很爽。

这也让我想到了 RxJava 中也提供了线程切换这样的功能,流式编程就显得更加的简洁明了,并且还不需要这样那样的注册,大总管之类的东西,所以现在大家都喜欢用RxJava。

EventBus其他功能介绍

StickyEvent

第一个是粘性事件,普通的事件我们通过post发送给EventBus,发送过后之后当前已经订阅过的方法可以收到。但是如果有些事件需要所有订阅了该事件的方法都能执行呢?例如一个Activity,要求它管理的所有Fragment都能执行某一个事件,但是当前我只初始化了3个Fragment,如果这时候通过post发送了事件,那么当前的3个Fragment当然能收到。但是这个时候又初始化了2个Fragment,那么我必须重新发送事件,这两个Fragment才能执行到订阅方法。

粘性事件就是为了解决这个问题,通过 postSticky 发送粘性事件,这个事件不会只被消费一次就消失,而是一直存在系统中,知道被 removeStickyEvent 删除掉。那么只要订阅了该粘性事件的所有方法,只要被register 的时候,就会被检测到,并且执行。订阅的方法需要添加 sticky = true 属性。

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
    textField.setText(event.message);
}

订阅权限 Subscriber Priorities

你可以通过 在@Subscribe(priority = 1)中添加 priority 来定义订阅的权限。权限越高的方法会在收到后越先执行。默认的 priority = 0

@Subscribe(priority = 1)
public void onEvent(MessageEvent event) {
    ...
}

取消事件分发

当你收到一个事件,并且调用 cancelEventDelivery 后,那么这个事件不会再往下分发,要知道,有可能不止一个方法订阅了该消息哦,取消后后面的方法就都收不到消息了。

// Called in the same thread (default)
@Subscribe
public void onEvent(MessageEvent event){
    // Process the event
    ...
    // Prevent delivery to other subscribers
    EventBus.getDefault().cancelEventDelivery(event) ;
}

还有其他的就自己看官网吧

写在最后的话

我也是才看EventBus,其实用起来的话感觉确实比以前的Handler那些机制要好用。但是EventBus这个大总管的方式其实我不太喜欢,如果项目不停迭代,代码越来越多,管理Message就变得很繁琐,出错也不好排查。而且这个大总管是单例哦,如果App一直运行,或并发数目比较多时,可能性能上会有一些问题,当然这只是自己的猜想而已,我还没有实践过。

老司机开开车,其实我不是老司机,学习一点内容,分享分享,希望能抛砖引玉。自己也写过很多的内容,总结下来也有一些经验,对于我们这些初学者来说,请记住一定学习一个新技术,新框架的时候,从官网入手,英文就英文,多看两遍就回了。所以我写过的每一篇笔记都是附上官网地址的,所以你还在等什么,看官网去吧,光看这点是不够的。

时间: 2024-12-28 21:46:12

EventBus 这一篇还不够的相关文章

EventBus 2.4 源码分析

EventBus简介 本篇基于EventBus 2.4撰写. Android optimized event bus that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality. 上面是从官方repo拉来的代码,大致是说简化的组件之间的交流通信,减少代码,提高质量. 其实和EventBus最早是在qzone的代码里认识的,空间内部有一个

在线协作沟通工具DesignBoard帮助设计团队更有效地进行沟通与版本管理

设计稿呈现缺乏整体性.远程沟通效率低.多版本管理混乱,这可能是很多创业团队都面临的问题,并且这些问题都将直接影响到产品开发进度.国内创业团队彩程设计也曾面临同样的问题,后来他们在做某个新项目时尝试把设计原型打印并按序张贴出来,结果发现效果居然还不错.于是基于这个流程,该团队创建了一个在线协作工具 -- “DesignBoard”. DesignBoard支持多人在线协作,参与者可以上传设计原型图片并进行任意排列布局,并且可以使用带箭头的曲线表示图片间的逻辑关系.点击打开每张图片的独立页面,可以对

Seafile 推出 “分布式文件同步技术” 打造的私有云服务

近两年来 Dropbox 等云储存服务迅速窜红,各大巨头纷纷推出自家的云储存服务(苹果的 iCloud, 微软的 SkyDrive, Google 即将推出的 GDrive),国内也有类似的服务(金山网盘.袋鼠盘.坚果云等).用户只需将自己的文件资料储存到这些云储存空间上,就可以从自己的台式机.手机.平板等终端设备随时随地访问自己的文件资料,用户如果在一个地方更新文件,其它地方也会自动同步. 挑战以 Dropbox 为代表的传统 “同步网盘”,Seafile 推出 “分布式文件同步技术” 打造的

拒绝收购邀请,三年专注开发,开源的私有云盘“迷你云”(十人团队在三年时间里靠自筹资金专注开发出来的作品)

来自36 氪开放日上海站. Dropbox 等云储存服务在近两年来迅速窜红,各大巨头也纷纷推出自家的云储存服务(苹果的 iCloud, 微软的 SkyDrive, Google 的 GDrive),国内也有类似的服务,金山网盘.袋鼠盘.坚果云等等,不胜枚举,俨然一片红海.从部署方式上说,上述的云存储服务统称为公有云. 同样是做云存储,近两年来私有云也逐渐为人们熟悉,比如我们此前就报道过 Seafile, Syncbox 等国内的私有云项目.相对于公有云来说,由有私有云通常都是建立在自己的服务器上

Android事件总线(二)EventBus3.0源码解析

相关文章 Android事件总线(一)EventBus3.0用法全解析 前言 上一篇我们讲到了EventBus3.0的用法,这一篇我们来讲一下EventBus3.0的源码以及它的利与弊. 1.构造函数 当我们要调用EventBus的功能时,比如注册或者发送事件,总会调用EventBus.getDefault()来获取EventBus实例: public static EventBus getDefault() { if (defaultInstance == null) { synchroniz

网络虚拟化—互联网的下一波革命

boxi • 2012-04-20 07:33 转自 36氪 编者注:最近几天开放网络峰会(Open Networking Summit)的召开掀起了一股软件定义网络(SDN)和OpenFlow的报道热潮.很多人相信,软件定义网络和OpenFlow主导的网络虚拟化必将 引发互联网的下一场革命.本文介绍这一行业的领军者之一,Nicira.其CTO Martin Casado是OpenFlow协议的第一份草案的撰稿人. 成立于5年前的Nicira被 认为是硅谷 最吸引人的初创企业.简单来说Nicir

诗经 全文

诗经 全文 (带注释和译文) http://www.edu009.com/Article/HTML/Article_60756.html <诗经> 春秋·孔丘 <诗经>是我国第一部诗歌总集,先秦时代称为“诗”或“诗三百”,孔子加以了整理.汉武帝采纳董仲舒“罢黜百家,独尊儒术”的建议,尊“诗”为经典,定名为<诗经>. <诗经>现存诗歌 305 篇,包括西周初年到春秋中叶共 500 余年的民歌和朝庙乐章,分为风.雅.颂三章. “风”包括周南.召南.邶.鄘.卫.王

消息处理之EventBus ——使用篇

以前的几篇文章简单的介绍了一下UI线程和子线程之间的线程通信利器Handler,以及顺便介绍了一下SyncTask和HeadlerThread.这里介绍另一线程通信利器EventBus. EventBus是一个开源组件.https://github.com/greenrobot/EventBus,通过线程间事件订阅和分发来完成消息传递,通过这种模式来降低组件之间的耦合度. 多说无益,直接看实例. 1 import android.support.v7.app.AppCompatActivity;

[android架构篇]mvp+rxjava+retrofit+eventBus

android架构篇 mvp+rxjava+retrofit+eventBus 高层不应该知道低层的细节,应该是面向抽象的编程.业务的实现交给实现的接口的类.高层只负责调用. 首先,要介绍一下一个项目中好架构的好处:好的软件设计必须能够帮助开发者发展和扩充解决方案,保持代码清晰健壮,并且可扩展,易于维护,而不必每件事都重写代码.面对软件存在的问题,必须遵守SOLID原则(面向对象五大原则),不要过度工程化,尽可能降低框架中模块的依赖性. 之前的一段时间,学习了一些新的技术,并把自己关注的技术整合