Android开发学习之路-EventBus使用
EventBus是一个通过发布、订阅事件实现组件间消息传递的工具。
它存在的目的,就是为了优化组件之间传递消息的过程。传统组件之间传递消息的方法有使用广播,回调等,而这些方法使用都比较复杂。
工作原理:
依赖:
dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
}
注:EventBus是事件-订阅模型,实际上事件就是消息,订阅就是接收,本文不会很严格区分,方便理解为主!
1. 从简单的入手:充当Handler
既然能发送消息,那么自然在同一个组件下也能进行消息的发送和接收,也就是Handler的职责。
先定义一个事件的对象:
public class MessageEvent {
private String message; public MessageEvent(String message) {
this.message = message;
} public String getMessage() {
return message;
} @Override
public String toString() {
return message;
}
}
这个事件对象只需要是Object的子类,没其他要求,消息的内容可以随意定,这里用一个String表示事件的消息,toString直接输出事件的内容。
在需要接收消息的组件中,进行EventBus的绑定,这里由Activity充当订阅者(Subscriber),也就是消息接收者。
public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} @Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this); // 将当前Activity绑定为订阅者
} @Override
protected void onStop() {
EventBus.getDefault().unregister(this); // 解绑
super.onStop();
} // 声明一个订阅方法,用于接收事件
@Subscribe
public void onEvent(MessageEvent messageEvent) {
Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
} }
通过EventBus.getDefault方法获取到一个EventBus的一个单例,也就是每次调用这个方法得到的都是同一个EventBus对象。而不同的EventBus对象消息不会互通。
接着需要在Activity的onStart方法中进行对EventBus对象的绑定,在onStop方法中进行解绑。同时,需要定义用于接收事件的方法,并加上@Subscribe注解表明该方法用于接收订阅事件。
接着,我们需要发送事件:
EventBus.getDefault().post(new MessageEvent("I m Fndroid"));
这里获取的默认的EventBus对象,通过post方法进行事件的发送,log如下:
2. 组件间通讯:代替广播、回调等
EventBus的存在,并不是为了替代Handler,而是用来进行组件间的通讯。有了上面的知识,接下来就不难了。
我们都知道,只要是同一个EventBus对象绑定的组件(Subscriber),消息是互通的,也就是我们可以在Service中向Activity发送事件进行通讯。(其他组件类似)
定义一个IntentService,并且发送一个事件,而Activity,和上面一样。
public class MyIntentService extends IntentService { public MyIntentService() {
super("MyIntentService");
} @Override
protected void onHandleIntent(Intent intent) {
EventBus.getDefault().post(new MessageEvent("From service"));
} }
在Activity中开启服务:
startService(new Intent(this, MyIntentService.class));
Log:
组件间的通讯变得如此简单了。
3. 进阶:持久事件、线程模式、优先级
① 持久事件(StickyEvent):对于调用post方法发送的普通消息,会在第一次被接收到的时候被消费掉,也就是我们在@Subscribe方法下处理完了,这个消息就消失了。而EventBus则提供了另一种类型的消息——StickyEvent,这个消息,会被保存在RAM中,直到下一个StickyEvent被发送才会被替换。每个EventBus对象都能通过geStickyEvent方法获取最近发出的持久事件。
我们对Activity稍作修改,在订阅方法中,把当前的持久消息打印出来:
// 声明一个订阅方法,用于接收事件
@Subscribe
public void onEvent(MessageEvent messageEvent) {
Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
Log.d(TAG, "onEvent: Sticky Event = [" + EventBus.getDefault().getStickyEvent(MessageEvent.class) + "]");
}
接着对Service也进行修改,令其发送一个StickyEvent:
@Override
protected void onHandleIntent(Intent intent) {
EventBus.getDefault().post(new MessageEvent("From service"));
EventBus.getDefault().postSticky(new MessageEvent("From service2"));
EventBus.getDefault().post(new MessageEvent("From service3"));
}
这里看到,在第二次发送的时候,调用了postSticky方法发送事件,这就表明了该事件是一个持久事件,除非有新的同类型(不同类型的事件可以共存)持久事件被发送,否则会一直被保存在内存中,我们任何时候都能获取得到。
Log:
可以看到,在第三次接收到消息的时候,将StickyEvent打印出来,依旧是"From service2"。
同样的,如果我们想要移除此持久事件,可以调用EventBus的removeStickyEvent方法来实现,如果要移除所有类型的持久事件,可以调用removeAllStickyEvent方法。
② 线程模式
EventBus允许我们对订阅者进行线程设置,默认情况下,订阅是和事件发送处于同一线程的,我们不妨把订阅的线程id打印出来看一看。
修改Activity中的@Subscribe方法:
@Subscribe
public void onEvent(MessageEvent messageEvent) {
Log.d(TAG, "onEvent: Thread id = [" + Thread.currentThread().getId() + "]");
Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
}
修改Service,让其发送一次普通事件,并且输出当前线程id:
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent: Thread id = [" + Thread.currentThread().getId() + "]");
EventBus.getDefault().post(new MessageEvent("From service"));
}
打印Log:
对于订阅者,有以下四种线程模式:
- POSTING:默认模式,订阅和事件发送在同一线程下进行
- MAIN:订阅在主线程下进行,可以直接修改UI
- BACKGROUND:如果事件发送在主线程,则订阅在子线程下进行,如果事件发送在子线程,则订阅也在该子线程中进行
- ASYNC:如果事件发送在主线程,则订阅在子线程下进行,如果事件发送在子线程,则订阅会在其他子线程中进行
设置订阅者线程很简单,只需要在注解中赋值即可,如:
@Subscribe(threadMode = ThreadMode.MAIN)
③ 优先级
每个组件中可以有多个订阅方法,而我们可以对它们设置不同的优先级,设置的方法也很简单:
@Subscribe(priority = 88)
默认的优先级为0,更高优先级的订阅方法会更先收到事件,而每个订阅方法都可以对事件进行终止,可以通过以下方法停止事件传递:
EventBus.getDefault().cancelEventDelivery(messageEvent);
④ 自定义EventBus对象
通过getDefault方法获取的是一个EventBus默认的单例,而我们可以通过EventBus.Builder来构造一个自定义的EventBus对象。
明白了用法以后,我们分析源码也会更加简单。
Android开发学习之路-EventBus使用的更多相关文章
- Android开发学习之路-RecyclerView滑动删除和拖动排序
Android开发学习之路-RecyclerView使用初探 Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析 Android开 ...
- Android开发学习之路--基于vitamio的视频播放器(二)
终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ...
- Android开发学习之路--Android Studio cmake编译ffmpeg
最新的android studio2.2引入了cmake可以很好地实现ndk的编写.这里使用最新的方式,对于以前的android下的ndk编译什么的可以参考之前的文章:Android开发学习之路– ...
- Android开发学习之路--网络编程之xml、json
一般网络数据通过http来get,post,那么其中的数据不可能杂乱无章,比如我要post一段数据,肯定是要有一定的格式,协议的.常用的就是xml和json了.在此先要搭建个简单的服务器吧,首先呢下载 ...
- Android开发学习之路--Activity之初体验
环境也搭建好了,android系统也基本了解了,那么接下来就可以开始学习android开发了,相信这么学下去肯定可以把android开发学习好的,再加上时而再温故下linux下的知识,看看androi ...
- Android开发学习之路--Android系统架构初探
环境搭建好了,最简单的app也运行过了,那么app到底是怎么运行在手机上的,手机又到底怎么能运行这些应用,一堆的电子元器件最后可以运行这么美妙的界面,在此还是需要好好研究研究.这里从芯片及硬件模块-& ...
- Android开发学习之路--MAC下Android Studio开发环境搭建
自从毕业开始到现在还没有系统地学习android应用的开发,之前一直都是做些底层的驱动,以及linux上的c开发.虽然写过几个简单的app,也对android4.0.3的源代码做过部分的分析,也算入门 ...
- Android开发学习之路-记一次CSDN公开课
今天的CSDN公开课Android事件处理重难点快速掌握中老师讲到一个概念我觉得不正确. 原话是这样的:点击事件可以通过事件监听和回调两种方法实现. 我一听到之后我的表情是这样的: 这跟我学的看的都不 ...
- Android开发学习之路-Android Studio开发小技巧
上一次发过了一个介绍Studio的,这里再发一个补充下. 我们都知道,Android Studio的功能是非常强大的,也是很智能的.如果有人告诉你学Android开发要用命令行,你可以告诉他Andro ...
随机推荐
- C#高性能TCP服务的多种实现方式
哎~~ 想想大部分园友应该对 "高性能" 字样更感兴趣,为了吸引眼球所以标题中一定要突出,其实我更喜欢的标题是<猴赛雷,C#编写TCP服务的花样姿势!>. 本篇文章的主 ...
- setAttribute()
●节点分为不同的类型:元素节点.属性节点和文本节点等. ●getElementById()方法将返回一个对象,该对象对应着文档里的一个特定的元素节点. ●getElementsByTagNam ...
- .net Elasticsearch 学习入门笔记
一. es安装相关1.elasticsearch安装 运行http://localhost:9200/2.head插件3.bigdesk插件安装(安装细节百度:windows elasticsear ...
- npm package.json属性详解
概述 本文档是自己看官方文档的理解+翻译,内容是package.json配置里边的属性含义.package.json必须是一个严格的json文件,而不仅仅是js里边的一个对象.其中很多属性可以通过np ...
- [C#] 简单的 Helper 封装 -- RandomHelper
using System; namespace Wen.Helpers { /// <summary> /// 随机数助手 /// </summary> public seal ...
- 从netty-example分析Netty组件续
上文我们从netty-example的Discard服务器端示例分析了netty的组件,今天我们从另一个简单的示例Echo客户端分析一下上个示例中没有出现的netty组件. 1. 服务端的连接处理,读 ...
- 微框架spark--api开发利器
spark简介 Spark(注意不要同Apache Spark混淆)的设计初衷是,可以简单容易地创建REST API或Web应用程序.它是一个灵活.简洁的框架,大小只有1MB.Spark允许用户自己选 ...
- CSS样式重置(转)
body,h1,h2,h3,h4,h5,h6,dl,dt,dd,ul,ol,li,th,td,p,blockquote,pre,form,fieldset,legend,input,button,te ...
- AJAX实现登录界面
使用php跳转界面和AJAX都可实现登录界面的跳转的登录失败对的提醒.但是,php跳转的方式 需要额外加载其他界面,用户体验差.AJAX可实现当前页面只刷新需要的数据,不对当前网页进行 重新加载或者是 ...
- 开源一款简单清爽的日历组件,JavaScript版的
源码会在最后给出地址,需要的朋友自己去下载.最近项目需要做一个日程安排的功能,就是点击日历的某一天弹出一个录入页面,填完信息后保存当天的日程安排.有日程的日期会有不同的标记(比如加一个背景色啥的).网 ...