事物总线模式实例——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 ...
随机推荐
- python 动态导入模块、断言
断言: 类似与判断,后面的程序依赖前面的,可以加一个断言,断言成功继续执行.断言失败报错停止执行. a = 'abc' assert type(a) is str print('yes') asser ...
- Tomcat 数据源的原理、配置、使用
1.数据源的作用及操作原理 在程序代码中使用数据源是可以提升操作性能的,这种性能的提升依靠于运行的原理. 传统JDBC操作步骤 1.加载数据库驱动程序,数据库驱动程序通过CLASSPATH配置: 2. ...
- xml linq
这里讲解一下linq对xml的基本操作,包括: 新建xml.新建节点 查询节点 插入属性.插入节点 替换节点 在这里我封装了一些常用的方法: public class XmlHelper { /// ...
- python功能
1.前端使用ajax 项目名字/views.py from django.shortcuts import render from django.http import JsonResponse fr ...
- 走进git
一.什么是git和githob? Git是一款免费.开源的分布式版本控制系统.Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件.Githu ...
- IOS 应用管理(九宫格) 总结笔记
1. 开发前的思路 ========================================1> 从mainBundle中加载Plist2> 按照plist中的数据数量先确定各个a ...
- 【题解】洛谷P1262 间谍网络 (强连通分量缩点)
洛谷P1262:https://www.luogu.org/problemnew/show/P1262 思路 一看题目就知道是强连通分量缩点 当图中有强连通分量时 将其缩点 我们可以用dfn数组判断是 ...
- An Algorithm for Surface Encoding and Reconstruction From 3D Point Cloud Data
An Algorithm for Surface Encoding and Reconstruction From 3D Point Cloud Data https://www.youtube.co ...
- java流汇总以及使用实例
流一.基本概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络) 读入到内存中,形成了流,然后将这些流还可以写到另外的目的地 ...
- Vue+node.js+express+mysql实例---对图书信息进行管理
一个简单的 CURD 实例 ---对图书信息进行管理 目录 1 开发环境 1.1 前端开发环境 1.2 后端开发环境 2 数据库设计和创建 2.1 数据库和表设计 2.2 book 表设计 2.3 s ...