前言

EventBus框架
EventBus是一个通用的叫法,例如Google出品的Guava,Guava是一个庞大的库,EventBus只是它附带的一个小功能,因此实际项目中使用并不多。用的最多的是greenrobot/EventBus,这个库的优点是接口简洁,集成方便,但是限定了方法名,不支持注解。另一个库square/otto修改自 Guava ,用的人也不少。所以今天我们研究的目标是greenrobot的EventBus.
EventBus 简介
1、EventBus3.0.0 是最新的版本。
2、EventBus 是Android 发布/订阅事件总线,可简化 Activities, Fragments, Threads, Services 等组件间的消息传递。
3、可替代 Intent, Handler, BroadCast ,接口等传统方案,更快,代码更小,50K 左右的 jar 包,代码更优雅,彻底解耦。
github地址:https://github.com/greenrobot/EventBus
EventBus原理图
如何添加依赖
在module的build.gredle 文件中的dependencies标签中添加
compile 'org.greenrobot:eventbus:3.0.0'
例如
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.3"
defaultConfig {
applicationId "com.eventbus.app"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'org.greenrobot:eventbus:3.0.0'
}
如何使用
注册事件
EventBus.getDefault().register( this );
取消注册
EventBus.getDefault().unregister( this );
发送数据
EventBus.getDefault().post( "我发射了");
简单小例子:使用EventBus传递简单字符串
package com.eventbus.app;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册
EventBus.getDefault().register( this );
findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post( "我发射了");
}
});
}
/**
* 自定义一个方法 hello() ,用来接收事件。
* 方法名字可以随便写
* @return
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void hello ( String event){
/* Do something */
Toast.makeText( this , event , Toast.LENGTH_SHORT).show();
};
@Override
protected void onDestroy() {
super.onDestroy();
//取消注册 , 防止Activity内存泄漏
EventBus.getDefault().unregister( this );
}
}
线程模型
在接收事件消息的方法中,可以通过注解的方式设置线程模型,EventBus内置了4中线程模型,分别是ThreadMode.POSTING 、ThreadMode.MAIN、ThreadMode.BACKGROUND、ThreadMode.ASYNC
比如:
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageEventPostThread(String event) {
Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventMainThread(String event) {
Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEventBackgroundThread(String event) {
Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEventAsync(String event) {
Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
PostThread:如果使用事件处理函数指定了线程模型为PostThread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为PostThread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。
MainThread:如果使用事件处理函数指定了线程模型为MainThread,那么不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。该方法可以用来更新UI,但是不能处理耗时操作。
BackgroundThread:如果使用事件处理函数指定了线程模型为BackgroundThread,那么如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
Async:如果使用事件处理函数指定了线程模型为Async,那么无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行UI更新操作。
小例子1: 在子线程发送数据
package com.eventbus.app;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册
EventBus.getDefault().register( this );
findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
EventBus.getDefault().post( "我发射了");
}
}).start() ;
}
});
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageEventPostThread(String event) {
Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventMainThread(String event) {
Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEventBackgroundThread(String event) {
Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEventAsync(String event) {
Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消注册 , 防止Activity内存泄漏
EventBus.getDefault().unregister( this );
}
}
运行结果:
D/event 发射数据线程 :: Thread-109
E/event BackgroundThread: 消息: 我发射了 thread: Thread-109
E/event PostThread: 消息: 我发射了 thread: Thread-109
E/event Async: 消息: 我发射了 thread: pool-1-thread-2
E/event MainThread: 消息: 我发射了 thread: main
小例子2: 在主线程发送数据
package com.eventbus.app;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册
EventBus.getDefault().register( this );
findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
EventBus.getDefault().post( "我发射了");
}
});
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageEventPostThread(String event) {
Log.e( "event PostThread", "消息: " + event + " thread: " + Thread.currentThread().getName() );
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventMainThread(String event) {
Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEventBackgroundThread(String event) {
Log.e( "event BackgroundThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEventAsync(String event) {
Log.e( "event Async", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消注册 , 防止Activity内存泄漏
EventBus.getDefault().unregister( this );
}
}
运行结果:
D/event 发射数据线程 :: main
E/event MainThread: 消息: 我发射了 thread: main
E/event PostThread: 消息: 我发射了 thread: main
E/event Async: 消息: 我发射了 thread: pool-1-thread-3
E/event BackgroundThread: 消息: 我发射了 thread: pool-1-thread-4
黏*件
除了上面讲的普通事件外,EventBus还支持发送黏*件。何为黏*件呢?简单讲,就是在发送事件之后再订阅该事件也能收到该事件,跟黏性广播类似。具体用法如下:
注册
EventBus.getDefault().register( this );
事件接收
@Subscribe(threadMode = ThreadMode.MAIN , sticky = true )
public void onMessageEventMainThread(String event) {
Log.e( "event MainThread", "消息: " + event + " thread: " + > Thread.currentThread().getName());
}
取消注册
EventBus.getDefault().unregister( this ) ;
发送事件
EventBus.getDefault().postSticky( "我发射了");
小例子:在MainActivity发送事件,在Activity2里注册并且接收事件
MainActivity源码
package com.eventbus.app;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import org.greenrobot.eventbus.EventBus;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById( R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d( "event 发射数据线程 : " , Thread.currentThread().getName() ) ;
EventBus.getDefault().postSticky( "我发射了");
startActivity( new Intent( MainActivity.this , Activity2.class ));
}
});
}
}
Activity2源码
package com.eventbus.app;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class Activity2 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
//注册
EventBus.getDefault().register( this );
}
@Subscribe(threadMode = ThreadMode.MAIN , sticky = true )
public void onMessageEventMainThread(String event) {
Log.e( "event MainThread", "消息: " + event + " thread: " + Thread.currentThread().getName());
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消注册 , 防止Activity内存泄漏
EventBus.getDefault().unregister( this ) ;
}
}
这就是粘*件,能够收到订阅之前发送的消息。但是它只能收到最新的一次消息,比如说在未订阅之前已经发送了多条黏性消息了,然后再订阅只能收到最近的一条消息。
EventBus源码分析
Subscribe 接口源码
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
/**
* If true, delivers the most recent sticky event (posted with
* {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
*/
boolean sticky() default false;
/** Subscriber priority to influence the order of event delivery.
* Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
* others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
* delivery among subscribers with different {@link ThreadMode}s! */
int priority() default 0;
}
可以看出默认的线程模型是ThreadMode.POSTING ;默认黏*件为false,也就是默认不开启黏*件;默认的优选级为0 。
EventBus 类部分源码
static volatile EventBus defaultInstance;
/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
getDefault() 是一个单例模式 , 只有一个实例对象。
ThreadMode 类源码
public enum ThreadMode {
/**
* Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery
* implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
* simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers
* using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
*/
POSTING,
/**
* Subscriber will be called in Android's main thread (sometimes referred to as UI thread). If the posting thread is
* the main thread, event handler methods will be called directly. Event handlers using this mode must return
* quickly to avoid blocking the main thread.
*/
MAIN,
/**
* Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods
* will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
* background thread, that will deliver all its events sequentially. Event handlers using this mode should try to
* return quickly to avoid blocking the background thread.
*/
BACKGROUND,
/**
* Event handler methods are called in a separate thread. This is always independent from the posting thread and the
* main thread. Posting events never wait for event handler methods using this mode. Event handler methods should
* use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
* of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus
* uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
*/
ASYNC
}
这个类是枚举类,定义了线程模型中的几种类型。
以上这篇Android EventBus 3.0.0 使用总结(必看篇)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
# android
# eventbus
# 3.0
# Android实现EventBus登录界面与传值(粘性事件)
# Android 消息分发使用EventBus的实例详解
# Android中使用开源框架eventbus3.0实现fragment之间的通信交互
# Android之利用EventBus发送消息传递示例
# Android 中 EventBus 的使用之多线程事件处理
# Android EventBus(普通事件/粘性事件)详解
# 射了
# 是一个
# 会在
# 是在
# 给大家
# 的人
# 就会
# 在这个
# 在此
# 这就是
# 也能
# 可以通过
# 希望能
# 然后再
# 自定义
# 只有一个
# 更快
# 不支持
# 可以看出
# 这篇
相关文章:
如何选择美橙互联多站合一建站方案?
如何在阿里云完成域名注册与建站?
定制建站流程步骤详解:一站式方案设计与开发指南
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
如何配置IIS站点权限与局域网访问?
网站插件制作软件免费下载,网页视频怎么下到本地插件?
C#如何使用XPathNavigator高效查询XML
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
视频网站制作教程,怎么样制作优酷网的小视频?
建站之星多图banner生成与模板自定义指南
宝塔建站教程:一键部署配置流程与SEO优化实战指南
深圳防火门网站制作公司,深圳中天明防火门怎么编码?
广东企业建站网站优化与SEO营销核心策略指南
实例解析angularjs的filter过滤器
网站企业制作流程,用什么语言做企业网站比较好?
建站主机默认首页配置指南:核心功能与访问路径优化
如何高效完成独享虚拟主机建站?
如何通过西部数码建站助手快速创建专业网站?
网站制作培训多少钱一个月,网站优化seo培训课程有哪些?
如何在IIS中新建站点并配置端口与物理路径?
网站制作模板下载什么软件,ppt模板免费下载网站?
网站制作网站,深圳做网站哪家比较好?
建站之星CMS建站配置指南:模板选择与SEO优化技巧
微网站制作教程,不会写代码,不会编程,怎么样建自己的网站?
如何通过wdcp面板快速创建网站?
如何快速辨别茅台真假?关键步骤解析
红河网站制作公司,红河事业单位身份证如何上传?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
公司网站设计制作厂家,怎么创建自己的一个网站?
建站之星后台管理系统如何操作?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
网站网页制作专业公司,怎样制作自己的网页?
免费视频制作网站,更新又快又好的免费电影网站?
网站制作企业,网站的banner和导航栏是指什么?
再谈Python中的字符串与字符编码(推荐)
建站主机核心功能解析:服务器选择与网站搭建流程指南
广德云建站网站建设方案与建站流程优化指南
自助网站制作软件,个人如何自助建网站?
高端建站三要素:定制模板、企业官网与响应式设计优化
如何高效配置香港服务器实现快速建站?
如何快速搭建二级域名独立网站?
香港服务器选型指南:免备案配置与高效建站方案解析
如何获取开源自助建站系统免费下载链接?
沈阳个人网站制作公司,哪个网站能考到沈阳事业编招聘的信息?
全景视频制作网站有哪些,全景图怎么做成网页?
c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗
网站制作公司,橙子建站是合法的吗?
大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?
网站制作新手教程,新手建设一个网站需要注意些什么?
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
*请认真填写需求信息,我们会在24小时内与您取得联系。