事物总线模式实例——EventBus实例详解
事件总线模式是一种广泛运用于安卓开发之中的一种软件架构模式,而事件总线模式在安卓开发中最广泛的应用莫过于AndroidStudio提供的EventBus,所以我就EventBus来谈谈对事件总线模式的认识。
EventBus是Android下高效的发布/订阅事件总线机制。作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment,Activity,Service,线程之间传递数据,执行方法。特点是代码简洁,是一种发布订阅设计模式(Publish/Subsribe),或称作观察者设计模式。我们可能对事物总线机制还是有点陌生,但是想必对23种软件设计模式之后的观察者模式应该很熟悉。事物总线模式就是观察者设计模式的一种,它的工作部件主要分为四种:事件源、事件监听器、通道和事件总线。它的主要工作原理:事件源将产生的消息发送到事件总线的特定通道之上,然后监听器在事先会订阅事务总线之中不同的通道以区分消息的响应,然后当消息被发送到事务总线的特定通道之中时,所对应的监听器会监听到消息,然后监听器根据程序中设置的响应函数进行执行。就好像一个Activity之中设置的Button一样,在xml文件中放入一个Button,然后在java类中设定OnEvent()函数,当Button被点击的时候,则会传出一个点击消息,然后按钮对应的Onclick()函数,监听到点击消息,从而执行OnListerner()之中的函数。
那么下面我们结合具体的实例来分析事件总线模式,提到这个模式我们第一个想到的一定是Adroid开发之中的一个组件——Event Bus。Event Bus是Android Studio官方为我们提供的一个工具包。下面我们就根据一个具体的框架来对Event Bus进行讲解。
我们想要实现的一个效果是,有两个acivity如图MainActivity:当点击"click"按钮的时候,就会跳转到secondActivity,而secondActivity里面有两个按钮,点击以后,可以改变MainActivity里面TextView的文字。
要实现这样的效果无非是完成一个消息的传递,相当于我们的观察者模式中发布者发布的一个消息,然后订阅者通过特定的通道进行监听,最后实现消息的传递。
首先是MainActivity:
public class MainActivity extends FragmentActivity {
Button btn;
TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getInstance().register(this);
btn = (Button) findViewById(R.id.btn);
text = (TextView) findViewById(R.id.text);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
}
public void onEvent(Info i){
Log.i("cky", i.msg);
}
public void onEventMain(Info i){
text.setText(i.msg);
}
public void onEventMain(Info2 i){
text.setText(text.getText()+i.msg);
}
}
从上面我们可以看出MainActivity的创建函数onCreate函数中调用了EventBus的register(this)函数,用来注册。然后是onEvent(),这个方法里面的代码,会在一个子线程中执行一个是onEventMain(),这个方法里面的代码,会在UI线程执行。
然后是SecondActivity
public class SecondActivity extends Activity {
Button btn2;
Button btn3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
btn2 = (Button) findViewById(R.id.btn2);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getInstance().post(new Info("信息1"));
}
});
btn3 = (Button) findViewById(R.id.btn3);
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getInstance().post(new Info2("信息2"));
}
});
}
}
那么这些活动之中的“始作俑者”——EventBus类又是什么样的呢?
public class EventBus {
HashMap<Class<?>,ArrayList<Subscription>> subscriptionsByEventType =
new HashMap<Class<?>,ArrayList<Subscription>>();
MainThreadHandler mainThreadHandler = new MainThreadHandler(this,Looper.getMainLooper());
AsyThreadHandler asyThreadHandler = new AsyThreadHandler(this);
private final static EventBus instance = new EventBus();
public static EventBus getInstance(){
return instance;
}
private EventBus(){};
}
在这其中:
register方法之中我们先获取了订阅者(例子中是MainActivity)的方法,找到onEvent开头的方法,获得它们的参数类型。然后判断subscriptionsByEventType是否有以这些参数类型为key的数据,如果没有,新建一个ArrayList<Subscription>。
Subscription它代表一个订阅,拥有subsriber,也就是订阅者还有一个SubscriberMethod,这是订阅方法类。
post()方法里面,如同我们上面所说,获取了参数类型,然后在subscriptionsByEventType中查询所有改类型对应的订阅Subscription对于Subscription,它有我们订阅类的所有信息。首先根据type判断是在主线程还是子线程执行,然后调用一开始讲到的两个类的实例就好了。
invoke()其实只有一句话,就是调用了反射去执行方法。m是订阅方法,sub.subscriber就是订阅者,event就是post()方法传入的实体这样我们就在子线程中调用了这个方法了,相当于MainActivity主动调用这个方法。
这便是事件总线模式的实例讲解,通过这个事例我们可以更加清晰地认识事件总线模式的结构和使用方法。
事物总线模式实例——EventBus实例详解的更多相关文章
- 安卓高级EventBus使用详解
我本来想写但是在网上看了下感觉写得不如此作者写得好:http://www.jianshu.com/p/da9e193e8b03 前言:EventBus出来已经有一段时间了,github上面也有很多开源 ...
- BS模式的模型结构详解
编号:1004时间:2016年4月12日16:59:17功能:BS模式的模型结构详解 URL:http://blog.csdn.net/icerock2000/article/details/4000 ...
- Vmware在NAT模式下网络配置详解
Vmware在NAT模式下网络配置详解 Linux中的网络配置对于接触Linux不久的小白菜来说,还是小有难度的,可能是不熟悉这种与windows系列迥然不同的命令行操作,也可能是由于对Linux的结 ...
- mybatis中的mapper接口文件以及example类的实例函数以及详解
##Example example = new ##Example(); example.setOrderByClause("字段名 ASC"); //升序排列,desc为降序排列 ...
- 实例-sprintf() 函数详解-输出格式转换函数
Part1:实例 $filterfile = basename(PHP_SELF, '.php'); if (isset($_GET['uselastfilter']) && isse ...
- curl库pycurl实例及参数详解
pycurl是功能强大的python的url库,是用c语言写的,速度很快,比urllib和httplib都快. 今天我们来看一下pycurl的用法及参数详解 常用方法: pycurl.Curl() # ...
- Android Developer -- Bluetooth篇 开发实例之四 API详解
http://www.open-open.com/lib/view/open1390879771695.html 这篇文章将会详细解析BluetoothAdapter的详细api, 包括隐藏方法, 每 ...
- MyBatis的Mapper接口以及Example的实例函数及详解
来源:https://blog.csdn.net/biandous/article/details/65630783 一.mapper接口中的方法解析 mapper接口中的函数及方法 方法 功能说明 ...
- MyBatis逆向工程中的Mapper接口以及Example的实例函数及详解
一.mapper接口中的方法解析 mapper接口中的函数及方法 方法 功能说明 int countByExample(UserExample example) thorws SQLException ...
随机推荐
- HTML基础内容(持续更新...)
1.<!DOCTYPE html>声明有助于浏览器中正确显示网页 HTML5<!DOCTYPE html>HTML 4.01<!DOCTYPE HTML PUBLIC & ...
- Python数组使用
python数组的使用 2010-07-28 17:17 1.Python的数组分三种类型: (1) list 普通的链表,初始化后可以通过特定方法动态增加元素. 定义方式:arr = [元素] (2 ...
- 最新一道面試題目,input: int[1,1,2,2,2,3,3,3],output [3,2,1],要求按照數字出現的次數從多到少排列元素。
面試當時沒有及時答出來,感覺當時在面試官的提示下跑偏了.想用兩個數組來mapping key和value然後對等排序,但是因為面試官讓用Array.sort而沒想好有什麼好辦法,結果可想而知.但是題目 ...
- 爬虫入门之爬取策略 XPath与bs4实现(五)
爬虫入门之爬取策略 XPath与bs4实现(五) 在爬虫系统中,待抓取URL队列是很重要的一部分.待抓取URL队列中的URL以什么样的顺序排列也是一个很重要的问题,因为这涉及到先抓取那个页面,后抓取哪 ...
- ORACLE_ALIAS
Oracle / PLSQL: ALIASES website:https://www.techonthenet.com/oracle/alias.php This Oracle tutorial e ...
- zt dup() 和 dup2()
dup() 和 dup2() 2011-10-07 11:06:31| 分类: Linux学习心得 |字号 订阅 dup和dup2都可用来复制一个现存的文件描述符,使两个文件描述符指向同一个fi ...
- 如何处理错误信息 Pricing procedure could not be determined
当给一个SAP CRM Quotation文档的行项目维护一个产品时,遇到如下错误信息:Pricing procedure could not be determined 通过调试得知错误消息在fun ...
- fiddler和charles
(4)学习浏览器代理和手机网络抓包,涉及到了fiddler和charles,
- Centos6.5(Linux)安装Nginx
1.安装nginx依赖的库pcre 下载地址:http://sourceforge.net/projects/pcre/ 2.解压pcre zip解压方式:unzip ...
- Python—面向对象05 反射
反射,通过字符串映射到对象属性 class People: country='China' def __init__(self,name,age): self.name=name self.age ...