前言
人生就是这样时而让你热血澎湃,时而让你撕心裂肺,你唯一能做的就是爱自己所爱,保持出心。
eventBus是用来做什么的
- 简单而强大: EventBus是一个超级简单易学的API库。尽管如此,您的软件体系结构可能会通过解耦组件获得很大的好处:订阅者在使用事件时不知道发件人。
- 测试对战: EventBus是最常用的Android库之一:数以千计的应用程序使用EventBus,包括非常流行的。超过十亿的应用程序安装说明一切。
- 高性能:特别是在Android上,性能至关重要。EventBus被分析和优化了很多; 可能使其成为同类中最快的解决方案。
- 基于方便注解的API (不牺牲性能):只需将@Subscribe注释放到订阅者方法中即可。由于注释的构建时间索引,EventBus不需要在应用运行时进行注释反射,这在Android上非常缓慢。
- Android主线程交付:当与UI进行交互时,无论事件如何发布,EventBus都可以在主线程中传递事件。
- 后台线程传递:如果您的订阅者执行长时间运行的任务,EventBus也可以使用后台线程来避免UI阻塞。
- 事件和订阅者继承:在EventBus中,面向对象的范例适用于事件和订阅者类。假设事件类A是B的超类。类型B的已发布事件也将发布给对A感兴趣的订阅者。类似地,考虑订阅者类的继承。
- 零配置: 您可以立即开始使用代码中任何位置的默认EventBus实例。
- 可配置: 为了根据需要调整EventBus,可以使用构建器模式调整其行为
eventBus的基本使用
一:定义事件
此处的意义在于定义一个eventBus进行事件处理的时候处理的对象,就比如登陆的请求 就需要定义一个 封装一个包含用户名,和密码的事件类。
二:首先注册eventBus
注册处理事件的对象 代码如下:
EventBus.getDefault().register(FristActivity.this);
三 :定义事件处理的方法
通过eventBus的注解定义处理事件的方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageReceive(MessageEvent event) {
textView.setText(event.getMessage());
}
四:事件的销毁
// 取消eventBus的注册
EventBus.getDefault().unregister(this);
程序截图
线程的切换
EventBus可以为您处理线程:事件可以在与发布线程不同的线程中发布。一个常见的用例是处理UI更改。在Android中,UI更改必须在UI(主)线程中完成。另一方面,网络或任何耗时的任务不能在主线程上运行。EventBus可以帮助您处理这些任务,并与UI线程同步(无需深入研究线程转换,使用AsyncTask等)。
在EventBus中,可以使用四个ThreadMode中的一个来定义将调用事件处理方法的线程
- 线程模式:posting
订阅者将在发布该事件的同一个帖子中被调用。这是默认的。事件传递是同步完成的,所有订阅者一旦发布完成就被调用。这个ThreadMode意味着最小的开销,因为它避免了完全的线程切换。因此,对于已知完成的简单任务而言,这是推荐的模式,其时间很短,不需要主线程。使用这种模式的事件处理程序应该快速返回以避免阻塞发布线程,这可能是主线程。例:
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageReceive2(MessageEvent event) {
textView.setText(event.getMessage());
}
- 线程模式 main
订阅者将在Android的主线程(有时称为UI线程)中被调用。如果发布线程是主线程,则将直接调用事件处理程序方法(与ThreadMode.POSTING中描述的同步)。使用此模式的事件处理程序必须快速返回以避免阻塞主线程。例:
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageReceive(MessageEvent event) {
textView.setText(event.getMessage());
}
- 线程模式 main_order
订阅者将在Android的主线程中被调用。该事件总是排队等待以后传递给订阅者,所以邮件的调用将立即返回。这给事件处理一个更严格和更一致的顺序(因此名字MAIN_ORDERED)。例如,如果使用MAIN线程模式在事件处理程序中发布另一个事件,则第二个事件处理程序将在第一个事件处理程序之前完成(因为它被同步调用 - 将其与方法调用进行比较)。使用MAIN_ORDERED,第一个事件处理程序将完成,然后第二个将在稍后的时间点被调用(只要主线程有能力)
public void onMessageReceive3(MessageEvent event) {
textView.setText(event.getMessage());
}
- 线程模式 background
订阅者将在后台线程中被调用。如果发布线程不是主线程,则会在发布线程中直接调用事件处理程序方法。如果发布线程是主线程,则EventBus将使用一个后台线程来按顺序发送所有事件。使用这种模式的事件处理程序应该尽快返回以避免阻塞后台线程。
public void onMessageReceive5(MessageEvent event) {
textView.setText(event.getMessage());
}
- 线程模式 async
事件处理程序方法在单独的线程中调用。这总是独立于发布线程和主线程。发布事件永远不会等待使用此模式的事件处理程序方法。事件处理程序方法应该使用这种模式,如果它们的执行可能需要一些时间,例如网络访问。避免同时触发大量长时间运行的异步处理程序方法来限制并发线程的数量。EventBus使用线程池有效地重用已完成异步事件处理程序通知中的线程。
public void onMessageReceive4(MessageEvent event) {
textView.setText(event.getMessage());
}
总结: 总的来说就是可以控制事件处理的线程可以在ui线程中处理,也可以在后台线程处理,等等
粘性事件
粘性事件就是事件可以发送但是我不订阅就不会做处理,只有订阅之后才会做处理,例如有这么一个场景我们需要检测下载的图片在图片下载结束的时候给予提示,我们就可以注册一个eventBus对象 在后台进行图片的下载我们会在下载的过程中使用evnetBus发送下载的进度,和完成的时候但是现在我们不限知道下载的进度只要知道下载完成就行了就可以使用粘性事件在发送进度的时候在下载完成的时候进行订阅处理。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().postSticky(new MessageEvent("我是粘性事件"));
finish();
}
});
// 订阅对事件进行处理
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().register(FristActivity.this);
}
});
- 粘性事件的获取
如您所见,最后的粘性事件会在注册时自动发送给匹配的订阅者。但有时手动检查粘性事件可能会更方便。也可能需要删除(消耗)粘性事件,以使它们不再被传递。例:
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}
事件的优先级
eventBus事件的优先级就是不同优先级之间的事件是不是可以接收,正常来说是高优先级的事件可以接收第优先级的事件 代码如下
@Subscribe(threadMode = ThreadMode.POSTING ,priority = 1)
public void MessageDeal(MessageEvent messageEvent){
Toast.makeText(this, "我的优先级是1"+messageEvent.getMessage(), Toast.LENGTH_SHORT).show();
//
}
@Subscribe(threadMode = ThreadMode.POSTING ,priority = 2)
public void MessageDeal1(MessageEvent messageEvent){
// 取消事件的传递 通常是更高优先级的事件取消对低优先级的事件的订阅
Toast.makeText(this, "我的优先级是2"+messageEvent.getMessage(), Toast.LENGTH_SHORT).show();
}
@Subscribe(threadMode = ThreadMode.POSTING ,priority = 3)
public void MessageDeal2(MessageEvent messageEvent){
Toast.makeText(this, "我的优先级是3"+messageEvent.getMessage(), Toast.LENGTH_SHORT).show();
}
在这段代码中优先级为三的事件可以接收另外两个事件
但有的时候我们不想事件继续传递就可以将他取消调
EventBus.getDefault().cancelEventDelivery(messageEvent);
订阅索引
订阅者索引是EventBus 3的一个新功能。这是一个可选的优化,以加速初始用户注册。
订阅者索引可以在构建时使用EventBus注释处理器创建。虽然不需要使用索引,但为了获得最佳性能,建议在Android上使用索引
这里只说一种比较简单的创建索引的方法,
- 使用annotationProcessor
1 在app的build.gradle中加入如下代码
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.xhh.eventbusdemo"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ]
}
}
}
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 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
// eventbus框架加载
compile 'org.greenrobot:eventbus:3.1.1'
// otto框架使用
compile 'com.squareup:otto:1.3.8'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
- 索引的使用
// 使用eventBus的索引
EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();
try {
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
} catch (Exception e) {
e.printStackTrace();
}
// 使用默认的索引
EventBus eventBus1 = EventBus.getDefault();
// 注册eventBus
eventBus1.register(this);
到此eventBus简单的使用已经结束了,内部的理论的描述大部分是官网上的
http://greenrobot.org/eventbus/documentation/