前言

EventBus是greenrobot再Android平台发布的以订阅-发布模式为核心的开源库。

EventBus翻译过来是事件总线意思。可以这样理解:一个个(event)发送到总线上,

然后EventBus根据已注册的订阅者(subscribers)来匹配相应的事件,进而把事件传递给订阅者,

这也是观察者模式的一个最佳实践。

我们平常开发中,当遇到Activity与Activity、Activity与Fragment之间的通信,往往采用intent,又

或者线程之间用Handler进行通信,这样代码会复杂很多,而使用EventBus极大简化两个组件之间俺的通信问题,

而且效率极高。而EventBus升级到3.0版本后,开发者能够自定义订阅方法名字,而没必要

规定以“o'n'Event'XX"开头的方法了,这样也自由化了很多,而且支持了粘性事件的分发等,因此学会使用EventBus3.0

对我们开发又极大的好处.

例子

布局

activity_main

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" > <TextView
android:id="@+id/tv_text"
android:textSize="20sp"
android:text="@string/app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击打开新的Activity"
android:id="@+id/secondActivityBtn"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="75dp" /> </RelativeLayout>

activity_second

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<EditText
android:id="@+id/et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="请输入要发送的消息"
/>
<Button
android:id="@+id/sendMessageBtn"
android:text="发送消息"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>

代码

public class MainActivity extends Activity {

    private TextView textView;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册成为订阅者
EventBus.getDefault().register(this);
textView = (TextView) findViewById(R.id.tv_text);
button = (Button) findViewById(R.id.secondActivityBtn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
} //订阅方法,当接收到事件的时候,会调用该方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent messageEvent){
Log.d("cylog","receive it");
textView.setText(messageEvent.getMessage());
Toast.makeText(MainActivity.this, messageEvent.getMessage(), Toast.LENGTH_SHORT).show();
} @Override
protected void onDestroy() {
super.onDestroy();
//解除注册
EventBus.getDefault().unregister(this);
}
}
public class SecondActivity extends Activity {
private EditText et;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
et = findViewById(R.id.et);
Button button = (Button) findViewById(R.id.sendMessageBtn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(TextUtils.isEmpty(et.getText().toString())){
Toast.makeText(SecondActivity.this, "请输入......", Toast.LENGTH_SHORT).show();
return;
}else {
EventBus.getDefault().post(new MessageEvent(et.getText().toString()));
finish();
} }
});
}
}

效果图

发送黏性事件Sticky Events

上面示例代码所说的情况是:当发送消息推送者推送消息的时候,订阅者会立马收到消息,它会把消息推送给它所有的订阅者.注意后面这句话:如果你希望在消息推送完成之后,让新注册的订阅者也能收到这条消息,这时候你可以试试Sticky Events,这个事件就像一个常驻广播,只要是有新的订阅者订阅了这个事件,就会收到消息.当然,有两点要求:

1.首先,发送的是黏性事件,代码将post改为postSticky

// EventBus.getDefault().post(new MessageEvent());
EventBus.getDefault().postSticky(new MessageEvent());

2.然后,订阅者要声明自己能够接收到黏性事件的消息:代码中@Subscribe注解中的sticky值为true,满足了这两点,就能愉快的玩耍了.

@Subscribe(sticky = true)
public void onMessageEvent(MessageEvent event) {
Log.i(TAG, "onMessageEvent: 我是sticky event 收到消息");
}

3.测试效果

把项目入口调整为ThridActivity

public class ThirdActivity extends Activity implements View.OnClickListener {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third); Button button1 = (Button) findViewById(R.id.sendStickyMessageBtn1);
Button button2 = (Button) findViewById(R.id.sendStickyMessageBtn2);
Button button3 = (Button) findViewById(R.id.sendStickyMessageBtn3);
Button button4 = (Button) findViewById(R.id.sendRegisterBtn);
button1.setOnClickListener(this);
button2.setOnClickListener(this);
button3.setOnClickListener(this);
button4.setOnClickListener(this); } @Override
public void onClick(View view) {
switch (view.getId()){
case R.id.sendStickyMessageBtn1:
EventBus.getDefault().postSticky(new MessageEvent("粘性事件1"));
Log.e("cylog","发送粘性事件1...");
break;
case R.id.sendStickyMessageBtn2:
EventBus.getDefault().postSticky(new MessageEvent("粘性事件2"));
Log.e("cylog", "发送粘性事件2...");
break;
case R.id.sendStickyMessageBtn3:
EventBus.getDefault().postSticky(new MessageEvent("粘性事件3"));
Log.e("cylog", "发送粘性事件3...");
break;
case R.id.sendRegisterBtn:
Log.e("cylog", "注册成为订阅者...");
EventBus.getDefault().register(this); break;
} } @Subscribe(sticky = true)
public void onEvent(MessageEvent messageEvent){
Log.e("cylog","接受到了来自EventBus的事件:"+messageEvent.getMessage());
} @Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
} }



那么很明显,只会接受到最后发送的粘性事件,在此之前的事件都接收不到。

线程模型

在EventBus的事件处理函数中需要指定线程模型,即指定事件处理函数运行所在的想线程。在上面我们已经接触到了EventBus的四种线程模型。那他们有什么区别呢?

在EventBus中的观察者通常有四种线程模型,分别是PostThread(默认)、MainThread、BackgroundThread与Async。

PostThread:如果使用事件处理函数指定了线程模型为PostThread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为PostThread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。

MainThread:如果使用事件处理函数指定了线程模型为MainThread,那么不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。该方法可以用来更新UI,但是不能处理耗时操作。

BackgroundThread:如果使用事件处理函数指定了线程模型为BackgroundThread,那么如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。

Async:如果使用事件处理函数指定了线程模型为Async,那么无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行UI更新操作。

为了验证以上四个方法,别人的例子

@Subscribe(threadMode = ThreadMode.PostThread)
public void onMessageEventPostThread(MessageEvent messageEvent) {
Log.e("PostThread", Thread.currentThread().getName());
} @Subscribe(threadMode = ThreadMode.MainThread)
public void onMessageEventMainThread(MessageEvent messageEvent) {
Log.e("MainThread", Thread.currentThread().getName());
} @Subscribe(threadMode = ThreadMode.BackgroundThread)
public void onMessageEventBackgroundThread(MessageEvent messageEvent) {
Log.e("BackgroundThread", Thread.currentThread().getName());
} @Subscribe(threadMode = ThreadMode.Async)
public void onMessageEventAsync(MessageEvent messageEvent) {
Log.e("Async", Thread.currentThread().getName());
}

分别使用上面四个方法订阅同一事件,打印他们运行所在的线程。首先我们在UI线程中发布一条MessageEvent的消息,看下日志打印结果是什么。

findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("postEvent", Thread.currentThread().getName());
EventBus.getDefault().post(new MessageEvent());
}
});

从日志打印结果可以看出,如果在UI线程中发布事件,则线程模型为PostThread的事件处理函数也执行在UI线程,与发布事件的线程一致。线程模型为Async的事件处理函数执行在名字叫做pool-1-thread-1的新的线程中。而MainThread的事件处理函数执行在UI线程,BackgroundThread的时间处理函数执行在名字叫做pool-1-thread-2的新的线程中。

我们再看看在子线程中发布一条MessageEvent的消息时,会有什么样的结果。

从日志打印结果可以看出,如果在子线程中发布事件,则线程模型为PostThread的事件处理函数也执行在子线程,与发布事件的线程一致(都是Thread-125)。BackgroundThread事件模型也与发布事件在同一线程执行。Async则在一个名叫pool-1-thread-1的新线程中执行。MainThread还是在UI线程中执行。

上面一个例子充分验证了指定不同线程模型的事件处理方法执行所在的线程。

EventBus 3.0: 入门使用及其使用 完全解析的更多相关文章

  1. 【热门技术】EventBus 3.0,让事件订阅更简单,从此告别组件消息传递烦恼~

    一.写在前面 还在为时间接收而烦恼吗?还在为各种组件间的消息传递烦恼吗?EventBus 3.0,专注于android的发布.订阅事件总线,让各组件间的消息传递更简单!完美替代Intent,Handl ...

  2. Android消息传递之EventBus 3.0使用详解

    前言: 前面两篇不仅学习了子线程与UI主线程之间的通信方式,也学习了如何实现组件之间通信,基于前面的知识我们今天来分析一下EventBus是如何管理事件总线的,EventBus到底是不是最佳方案?学习 ...

  3. Android EventBus 3.0.0 使用总结

    转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6039221.html 本文出自[赵彦军的博客] 前言 EventBus框架 EventBus是一个通用的叫法 ...

  4. ASP.NET Core 1.0 入门——了解一个空项目

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  5. ASP.NET Core 1.0 入门——Application Startup

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  6. EventBus 3.0使用

    在没用eventBus之前一直用Android广播方式通知消息更新UI 广播写法 首先发送广播通知 Intent intent = new Intent(); intent.setAction(&qu ...

  7. Omnet++ 4.0 入门实例教程

    http://blog.sina.com.cn/s/blog_8a2bb17d01018npf.html 在网上找到的一个讲解omnet++的实例, 是4.0下面实现的. 我在4.2上试了试,可以用. ...

  8. 《VC++ 6简明教程》即VC++ 6.0入门精讲 学习进度及笔记

    VC++6.0入门→精讲 2013.06.09,目前,每一章的“自测题”和“小结”三个板块还没有看(备注:第一章的“实验”已经看完). 2013.06.16 第三章的“实验”.“自测题”.“小结”和“ ...

  9. spring web flow 2.0入门(转)

    Spring Web Flow 2.0 入门 一.Spring Web Flow 入门demo(一)简单页面跳转 附源码(转) 二.Spring Web Flow 入门demo(二)与业务结合 附源码 ...

随机推荐

  1. Python9-MySQL-MySQL-ORM框架-day48

    ORM框架:AQLAlchemy-作用: 1.提供简单的规则 2.自动转换成SQL语句 -DB first: 手动创建数据库以及表 -> ORM框架 -> 自动生成类 code first ...

  2. linux下编译运行TIGL Viewer步骤

    linux下编译运行TIGL Viewer步骤(仅为了正确编译安装的话直接跳到步骤3) 1. linux发行版选择:由于linux发行版众多,不同版本包含的库版本可能存在差别,因此需要选择正确的版本. ...

  3. Asp.net自定义控件开发任我行(5)-嵌入资源上

    摘要 上一篇我们讲了VitwState保存控件状态,此章我们来讲讲嵌入css文件,js文件,嵌入Image文件我也一笔带过. 内容 随着我的控件的完善,我们目标控件DropDwonCheckList最 ...

  4. WampServer配置说明

    注意:所有的修改操作都要重启WampServer服务器,部分需要重启WampServer软件 1.修改默认端口 1)打开文件:C:\wamp\bin\apache\apache2.4.9\conf\h ...

  5. 实时视频h5

    http://www.cnblogs.com/dotfun/p/4286878.html

  6. IOS开发学习笔记042-UITableView总结2

    一.自定义非等高的cell         如常见的微博界面,有的微博只有文字,有的有文字和图片.这些微博的高度不固定需要重新计算. 这里简单说一下几种方法.前面的步骤和设置等高的cell一样.现在来 ...

  7. PyInstaller打包python脚本

    用python写的工具写好了,想打包然后发给测试同事使用,最后选择了PyInstaller,支持Windows.Linux.OS X,支持打包成一个文件夹或单个EXE文件.   我是直接在线安装的,在 ...

  8. 如何选择Android自动化框架的几点拙见

    首先由于我自己也是个新手,也是在学习各种框架然后给公司项目选定相应自动化框架,研究移动自动化测试框架也就近段时间而已,所以我只能从我自己今天为止的认知角度给各个框架抒发我自己的拙见,你看是否能从中接纳 ...

  9. C# 序列化和反序列化 详解

    什么是序列化以及如何实现序列化? 如何将对象数据写入 XML 文件? 如何从 XML 文件读取对象数据? 什么是序列化以及如何实现序列化? 序列化是通过将对象转换为字节流,从而存储对象或将对象传输到内 ...

  10. startActivityForResult用法

    使用场景:A界面(activity) 可跳转到一个(假设为 B)或多个子Activity,要求B处理完工作之后返回A 界面,或许同时返回一些数据交给A继续处理.如 由登陆界面A跳转到注册界面B,注册成 ...