EventBus 3.0使用详解
01 前言
当我们进行项目开发的时候,往往是需要应用程序的各组件、组件与后台线程间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过Handler或者是广播通知UI,而两个Fragment之家可以通过Listener进行通信等等。当我们的项目越来越复杂,使用Intent、Handler、Broadcast进行模块间通信、模块与后台线程进行通信时,代码量大,而且高度耦合。现在就让我们来学习一下EventBus 3.0吧。
02 什么是EventBus
EventBus Github地址
进入官网,看看人家是怎么解释的:
- simplifies the communication between components
decouples event senders and receivers
performs well with Activities, Fragments, and background threads
avoids complex and error-prone dependencies and life cycle issues- makes your code simpler
- is fast
- is tiny (~50k jar)
- is proven in practice by apps with 100,000,000+ installs
- has advanced features like delivery threads, subscriber priorities, etc.
大概的意思就是:EventBus能够简化各组件间的通信,让我们的代码书写变得简单,能有效的分离事件发送方和接收方(也就是解耦的意思),能避免复杂和容易出错的依赖性和生命周期问题。
03 关于EventBus的概述
三要素
- Event 事件。它可以是任意类型。
- Subscriber 事件订阅者。在EventBus3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
- Publisher 事件的发布者。我们可以在任意线程里发布事件,一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。
四种线程模型
EventBus3.0有四种线程模型,分别是:
- POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程。
- MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
- BACKGROUND 表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
- ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
04 EventBus的基本用法
举个例子,我需要在一个Activity里注册EventBus事件,然后定义接收方法,这跟Android里的广播机制很像,你需要首先注册广播,然后需要编写内部类,实现接收广播,然后操作UI。所以,在EventBus中,你同样得这么做。
自定义一个事件类
public class MessageEvent{
private String message;
public MessageEvent(String message){
this.message=message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
这里有些同学,会有一些疑问,为什么要建立这样一个类,有什么用途。其实这个类就是一个Bean类,里面定义用来传输的数据的类型。
注册事件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
}
当我们需要在Activity或者Fragment里订阅事件时,我们需要注册EventBus。我们一般选择在Activity的onCreate()方法里去注册EventBus,在onDestory()方法里,去解除注册。
解除注册
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
发送事件
EventBus.getDefault().post(messageEvent);
处理事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
...
}
前面我们说过,处理消息的方法名字可以随便取。但是需要加一个注解@Subscribe,并且要指定线程模型。
05 EventBus使用实战
以上我们讲了EventBus的基本用法,没有用过的同学也不要担心不会用,小编在这里举个小栗子。
第一步:添加依赖
compile 'org.greenrobot:eventbus:3.0.0'
第二步:定义消息事件类
public class MessageEvent{
private String message;
public MessageEvent(String message){
this.message=message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
第三步:注册和解除注册
分别在FirstActivity的onCreate()方法和onDestory()方法里,进行注册EventBus和解除注册。
package com.example.lenovo.testapp.ui;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.lenovo.testapp.R;
import com.example.lenovo.testapp.event.MessageEvent;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/**
* Created by ZZG on 2018/1/10.
*/
public class FirstActivity extends AppCompatActivity {
private Button mButton;
private TextView mText;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_activity);
mButton = (Button) findViewById(R.id.btn1);
mText = (TextView) findViewById(R.id.tv1);
mText.setText("今天是星期三");
EventBus.getDefault().register(this);
jumpActivity();
}
private void jumpActivity() {
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
});
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void Event(MessageEvent messageEvent) {
mText.setText(messageEvent.getMessage());
}
@Override
protected void onDestroy() {
super.onDestroy();
if(EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this);
}
}
}
事件处理
在这里,事件的处理线程在主线程,是因为,我要让TextView去显示值。
在 SecondActivity里去进行事件的发送。
package com.example.lenovo.tezs;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import org.greenrobot.eventbus.EventBus;
/**
* Created by ZZG on 2018/1/10.
*/
public class SecondActivity extends AppCompatActivity {
private Button mButton2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_activity);
mButton2=(Button) findViewById(R.id.btn2);
jumpActivity();
}
private void jumpActivity() {
mButton2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post(new MessageEvent("欢迎大家浏览我写的博客"));
finish();
}
});
}
}
很简单,当点击按钮的时候,发送了一个事件。
运行程序。
在FirstActivity中,左边是一个按钮,点击之后可以跳转到SecondActivity,在按钮的右边是一个TextView,用来进行结果的验证。
这是SecondActivity,在页面的左上角,是一个按钮,当点击按钮,就会发送了一个事件,最后这个Activity就会销毁掉。
此时我们可以看到,FirstActivity里的文字已经变成了,我们在SecondActivity里设置的文字。
总结
经过这个简单的例子,我们发现EventBus使用起来是如此的方便,当我们的代码量变得很多的时候,使用EventBus后你的逻辑非常的清晰,并且代码之间高度解耦,在进行组件、页面间通信的时候,EventBus是一个不错的选择。
作者:hz栗子哥
链接:https://www.jianshu.com/p/f9ae5691e1bb
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
EventBus 3.0使用详解的更多相关文章
- Android消息传递之EventBus 3.0使用详解
前言: 前面两篇不仅学习了子线程与UI主线程之间的通信方式,也学习了如何实现组件之间通信,基于前面的知识我们今天来分析一下EventBus是如何管理事件总线的,EventBus到底是不是最佳方案?学习 ...
- 【转】EventBus 3.0使用详解
原文:https://www.jianshu.com/p/f9ae5691e1bb 01 前言 当我们进行项目开发的时候,往往是需要应用程序的各组件.组件与后台线程间进行通信,比如在子线程中进行请求数 ...
- [转载]AxureRP 7.0部件详解(一)
本文为Axure RT7.0教程,本章主要介绍menu菜单.table表格.Tree Widget 树部件三个部件,后续将持续更新...... Menu 菜单 常用案例 网站导航菜单部件通常用于母板之 ...
- Cocos2d-x 3.0坐标系详解(转载)
Cocos2d-x 3.0坐标系详解 Cocos2d-x坐标系和OpenGL坐标系相同,都是起源于笛卡尔坐标系. 笛卡尔坐标系 笛卡尔坐标系中定义右手系原点在左下角,x向右,y向上,z向外,OpenG ...
- NPOI2.2.0.0实例详解(十)—设置EXCEL单元格【文本格式】 NPOI 单元格 格式设为文本 HSSFDataFormat
NPOI2.2.0.0实例详解(十)—设置EXCEL单元格[文本格式] 2015年12月10日 09:55:17 阅读数:3150 using System; using System.Collect ...
- windows版mysql8.0安装详解
2018年07月04日 13:37:40 Zn昕 阅读数 6433更多 分类专栏: mysql 版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. ...
- Vue1.0用法详解
Vue.js 不支持 IE8 及其以下版本,因为 Vue.js 使用了 IE8 不能实现的 ECMAScript 5 特性. 开发环境部署 可参考使用 vue+webpack. 基本用法 1 2 3 ...
- vue-cli3.0配置详解
这次给大家带来vue-cli3.0配置详解,使用vue-cli3.0配置的注意事项有哪些,下面就是实战案例,一起来看一下. 新建项目 1 2 3 4 5 6 7 8 # 安装 npm install ...
- .NET ORM框架 SqlSuagr4.0 功能详解与实践【开源】
SqlSugar 4.0 ORM框架的优势 为了未来能够更好的支持多库分布式的存储,并行计算等功能,将SqlSugar3.x全部重写,现有的架构可以轻松扩展多库. 源码下载: https://gith ...
随机推荐
- SQL Server进阶 窗口函数
概述 设计窗口函数目的? 在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成. 为了解决这些问题,在 2003 年 ISO SQL 标准加入了 ...
- win10和Ubuntu双系统安装过程中遇到的问题
1.安装过程 注意分区问题,很重要 https://blog.csdn.net/baobei0112/article/details/77996570 https://blog.csdn.net/s7 ...
- mouseover,mouseout与mouseenter,mouseleave
针对单个元素,使用感一样. 差异提现在有子元素的情况下: mouseover和mouseout在父元素和其子元素都可以触发,当鼠标穿过一个元素时,触发次数得依子元素数量而言. mouseenter和m ...
- hibernate多表操作
一.表之间的关系 1.一对一 2.一对多 3.多对多 二.表之间关系建表原则 1.一对多:在多的一方创建一个外键,指向一的一方的主键 2.多对多:创建一个中间表,中间表至少有两个字段,分别作为外键指向 ...
- 使用 JavaScript 将网站后台的数据变化实时更新到前端
问:难道只能设置定时器每隔一秒通过 Ajax 向后台请求数据来实现吗? 答: 1. nodejs的 http://socket.io 支持上述 李宏训 所说的三种方式,另外还支持 Flash Sock ...
- light oj 1254 - Prison Break 最短路
题目大意:n个点m条边的有向图,q次询问c,s,t,表示汽车邮箱容量为c,求从起点s到终点t的最小费用.汽车在每个点可以加任意的油,每个点的单位油价为a[i]. 题目思路:利用最小费优先队列优化最短路 ...
- 20165237 2017-2018-2 《Java程序设计》第四周考试补做及2-3章编程题
20165237 2017-2018-2 <Java程序设计>第四周考试补做及2-3章编程题 测试JDB: 用JDB调试上一个程序,输入1.2.3: 2-3章编程题代码托管 (程序的运行结 ...
- laravel 关闭 csrf 验证 TokenMismatchException
csrf验证失败 注释掉kernel.php 的 csrf 行代码
- python中模块的__all__属性
python模块中的__all__属性,可用于模块导入时限制,如:from module import *此时被导入模块若定义了__all__属性,则只有__all__内指定的属性.方法.类可被导入. ...
- LwIP Application Developers Manual5---高层协议之DHCP,AUTOIP,SNMP,PPP
1.前言 本文主要讲述高层协议,包括DHCP 2.DHCP 2.1 从应用的角度看DHCP 你必须确保在编译和链接时使能DHCP,可通过在文件lwipopts.h里面定义LWIP_DHCP选项,该选项 ...