eventbus可以让我们在不同的页面不同的组件之间传递消息,代码简介,使用方便并且可以将发送者和接受者解耦。
关于EventBus2.0的使用可以参考我的另外两篇博客:
eventbus的使用(一)简洁易懂 - 秦时明月 - CSDN博客
https://blog.csdn.net/baidu_31093133/article/details/51726745
eventbus的使用(二)简洁易懂 - 秦时明月 - CSDN博客
https://blog.csdn.net/baidu_31093133/article/details/51727135
本篇博客来说说EventBus3.0的使用O(∩_∩)O
1、EventBus2.0和3.0的区别
1.1
首先是性能上的区别,3.0的反射效率比2.x要低1~3倍,但是开启了索引系统的3.0速度要比2.x快很多,所以我们在使用3.0的时候通常都会开启索引系统。
2.x采用的是运行时注解,运行时注解很大基础上是依赖于java的反射机制实现的,而运行时注解是在运行时使用反射,并且会在反射的过程中会对注册的类的所有的方法进行扫描,所以是耗费性能的,这在一些低端机上尤为明显。
3.0采用的是编译时注解,在java文件编译生产.class文件的时候就已经创建出需要的类和索引关系,并将索引关系编译到apk中,这就比运行的时候再动态的使用反射速度要快。
除了两种注解方式的性能差异外,3.0还加入了对象池缓存并做了一些优化,来减少创建对象的开销。
1.2
第二点是书写方式的区别EventBus有三个主要组成部分:Publisher(事件发布者)、Event(事件)、Subscriber(事件订阅者),工作流程就是发布者发布事件给订阅者
EventBus3.0的事件发布者和事件的书写方式是一致的,最重要的区别在于订阅者。
2.0的订阅者只提供了四个函数onEvent,onEventMainThread,onEventBackgroundThread,onEventAsync并且只能用这四个函数来接受事件。
而3.0的接受方法是自己随意书写的,只需要在方法上添加需要的注解即可,下面我们通过实际使用来体会一下。
2、EventBus3.0的使用
1、导入eventbus
在gradle里面配置
implementation 'org.greenrobot:eventbus:3.1.1'
在同一个activity里:
1、在创建页面的时候注册eventbus
2、在销毁页面的时候注销eventbus
3、使用eventbus.post发送消息
4、消息是一个Object对象
首先我们创建一个类作为事件
public class ClickEvent {
}
接下来是activity的代码
public class MainActivity extends AppCompatActivity {
private Button btnSend;
private TextView tvReceive;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//在接受消息的activity里注册eventbus
EventBus.getDefault().register(this);
btnSend = (Button) findViewById(R.id.btn_send);
tvReceive = (TextView) findViewById(R.id.tv_receive);
btnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//使用post发送事件
EventBus.getDefault().post(new ClickEvent());
}
});
}
//接受消息
@Subscribe
public void onReceiveClickEvent(ClickEvent clickEvent) {
tvReceive.append("收到一条消息\n");
}
@Override
protected void onDestroy() {
super.onDestroy();
//页面销毁的时候注销eventbus
EventBus.getDefault().unregister(this);
}
效果图:
我们每点击一次按钮就会发送一次事件
接下来我们测试一下在不同的页面传递数据
我们创建一个ReceiveEventActivity,在这个activity里接受MainActivity发出的事件
效果图:
在MainActivity里发了6次事件,在ReceiveEventActivity里接受了6次
代码如下:
public class ReceiveEventActivity extends AppCompatActivity {
private TextView tvReceive;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_receive_event);
//注册eventbus
EventBus.getDefault().register(this);
tvReceive = (TextView) findViewById(R.id.tv_receive);
findViewById(R.id.btn_jump).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(ReceiveEventActivity.this, MainActivity.class));
}
});
}
//接受事件
@Subscribe
public void onReceiveClickEvent(ClickEvent clickEvent) {
tvReceive.append("ReceiveEventActivity 收到一条消息\n");
}
@Override
protected void onDestroy() {
super.onDestroy();
//注销eventbus
EventBus.getDefault().unregister(this);
}
}
可以发现,eventbus使用起来很方便很简单
接下来介绍一下eventbus的线程
//接受事件
@Subscribe//在这里指定线程
public void onReceiveClickEvent(ClickEvent clickEvent) {
tvReceive.append("ReceiveEventActivity 收到一条消息\n");
}
我们在接受事件的函数上使用了@Subscribe描述符
###我们可以指定接受事件的线程,一共有四种类型:
//与发送事件运行在同一个线程(默认的线程类型)
@Subscribe(threadMode = ThreadMode.POSTING)
// 在主线程中运行也就是UI线程
@Subscribe(threadMode = ThreadMode.MAIN)
// 在后台线程中运行
@Subscribe(threadMode = ThreadMode.BACKGROUND)
// 在另外的独立的线程中执行
@Subscribe(threadMode = ThreadMode.ASYNC)
大家可以自己做实验验证一下哦
###另外我们还可以指定接受事件的优先级
上面的例子中我在ReceiveEventActivity和MainActivity里都接受了事件,我们可以给这两个接受者指定优先级。
ReceiveEventActivity里:
//接受事件
@Subscribe(priority = 2)
public void onReceiveClickEvent(ClickEvent clickEvent) {
tvReceive.append("ReceiveEventActivity 收到一条消息\n");
}
MainActivity里:
//接受事件
@Subscribe(priority = 1)
public void onReceiveClickEvent(ClickEvent clickEvent) {
tvReceive.append("收到一条消息\n");
}
###数字越大优先级越高
设置优先级以后的效果:
可以看到(有一点模糊T.T)是ReceiveEventActivity先接受到事件,MainActivity后收到事件。
以上就是eventbus的简单实用了。
###进阶:
上面的方式都是通过反射的方式获取订阅方法,我们也可以实用annotationProcessor (注释处理工具)来处理,这样的的效率高一点。
然后在app的gradle下面添加:
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [eventBusIndex: 'study.com.interpolatortestdemo.EventBusIndex']
}
}
}
dependencies {
implementation 'org.greenrobot:eventbus:3.1.1'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
我的整个build文件:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "study.com.interpolatortestdemo"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions{
annotationProcessorOptions {
arguments = [ eventBusIndex : 'com.example.EventBusIndex' ]//这个是EventBusIndex的路径
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'org.greenrobot:eventbus:3.1.1'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}
这里要特别特别特别注意一件事:如果我们要引入索引,我们的项目里必须必须要有EventBus的@Subscribe注解,如果没有的话Eventbus的解释器是不会生成EventBus的索引文件的!
如图,如果我把@Subscribe注释掉的话,是不会产生EventBusIndex的
但我打开注释以后就会生成啦
我们的项目里使用过EventBus的注解@Subscribe以后,然后rebuild
然后在App类中:
public class App extends Application{
@Override
public void onCreate() {
super.onCreate();
//将MyEventBusIndex安装到默认的eventbus对象里
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
}
}
然后就可以和正常的eventbus一样实用啦:
修改后的MainActivity :
public class MainActivity extends AppCompatActivity {
private Button btnSend;
private TextView tvReceive;
private EventBus eventBus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//使用订阅者索引方式比反射方式的效率高,这里获取的默认eventbus已经安装了我们的MyEventBusIndex对象了
eventBus = EventBus.getDefault();
eventBus.register(this);
// EventBus.getDefault().register(this);
btnSend = (Button) findViewById(R.id.btn_send);
tvReceive = (TextView) findViewById(R.id.tv_receive);
btnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
eventBus.post(new ClickEvent());
}
});
}
@Subscribe(priority = 1)
public void onReceiveClickEvent(ClickEvent clickEvent) {
tvReceive.append("收到一条消息\n");
Log.i("LHD", "MainActivity收到事件");
}
@Override
protected void onDestroy() {
super.onDestroy();
// EventBus.getDefault().unregister(this);
eventBus.unregister(this);
}
}
另外EventBus还可以发送黏性事件,即发送事件之后再订阅该事件也能收到该事件,和黏性广播类似。
我们只需要在发送事件的时候使用eventBus.postSticky()方法,在订阅事件的时候增加sticky - true 即可,如:@Subscribe(threadMode = ThreadMode.POSTING,sticky = true)
然后注册EventBus以后就能收到该事件啦,这里就不在演示啦,大家可以下载代码以后自己做实验哦。
下一篇将分析EventBus3.0的实现原理。
代码下载:
下载后先rebulid一下生成MyEventBusIndex再运行哦
eventbus3.0 demo-CSDN下载
http://download.csdn.net/download/baidu_31093133/10141993