翻了一遍EventBus官方文档

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

Note:文章基于EventBus3.0

Paste_Image.png

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

先来聊聊:什么是通信?

Wiki中国: 通信是发送者通过某种媒体以某种格式来传递信息到收信者以达致某个目的。在古代,人们通过驿站飞鸽传书、烽火报警、符号语言、眼神、触碰等方式进行信息传递。到了今天,随着科技水平的飞速发展,通信基本完全利用有线或无线电完成,相继出现了有线电话固定电话无线电话手机互联网甚至视频电话等各种通信方式。通信技术拉近了人与人之间的距离,提高了通信的效率,深刻的改变了人类的通信。交流也是一种方法让其他人理解你。

上面是Wiki的解释,通信本身是个很抽象,宽泛的词, 你跟朋友打个电话叫通信, 发个Email也叫通信, 两个App之间传数据也叫通信,也叫为进程间通信, Activity和Activity之间传递数据叫组件间通信, 说到这里,来下个通俗点的定义:一个东西给另一个东西传递东西(数据),就叫通信.

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

方便Android组件间相互通信.在Activity,Service,Fragment之间传递数据,例如,你在个人主页编辑头像的界面修改了头像,这时候其它页面的头像也需要去修改,这时候可以试试EventBus.
基于观察者模式:这个好理解, 有消息的发送者,也有消息的接收者,当然,也可以是一发送者对应多个接收者, EventBus使用起来非常简单,可以用来提供广播之类

怎么用?

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

添加依赖

  compile 'org.greenrobot:eventbus:3.0.0'

使用三步曲:

1,定义事件类

事件类是通信过程中的数据的载体,用来传递数据,这里写一个最简单的事件类,后面说如何传递数据

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

2.注册事件

上面提到数据的发送者和接收者, 注册事件是针对接收者的, 哪个组件需要接收消息,就在哪个组件中去注册

  • 注册: EventBus.getDefault().register(this);
  • 添加函数注解@Subscribe:当数据的发送者发出消息后,添加这个注解的函数会被调用
  • 添加@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.发送事件

最后,消息的发送者发送事件, 这时候上面添加@Subscribe注解的函数会被调用

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

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

Paste_Image.png

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


Paste_Image.png

如果你打算把注册写在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;
  }
}

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(MessageEvent event) {
  Log.i(TAG, "onMessageEvent: 我是sticky event 收到消息");
}

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

测试Log日志


Paste_Image.png

接收事件的优先级别

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
![](/assets/EventBus Annotaion Processor.png)

用法:将它配置应用于默认的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

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 对于Android开发老司机来说肯定不会陌生,它是一个基于观察者模式的事件发布/订阅框架,开发者可以通过极少的代码...
    飞扬小米阅读 1,467评论 0 50
  • EventBus 是一个Android端优化的 publish/subscribe 消息总线,简化了应用程序各个组...
    王世军Steven阅读 1,845评论 4 21
  • 前言:EventBus出来已经有一段时间了,github上面也有很多开源项目中使用了EventBus。所以抽空学习...
    Kerry202阅读 1,280评论 1 2
  • 不是只有言语, 才承载着爱。 它是那么的轻盈, 无声无息, 无处不在。 是阳光亲吻万物的温度, 是月光投入大地的依...
    衿灵阅读 235评论 0 0