事件总线模式是一种广泛运用于安卓开发之中的一种软件架构模式,而事件总线模式在安卓开发中最广泛的应用莫过于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实例详解的更多相关文章

  1. 安卓高级EventBus使用详解

    我本来想写但是在网上看了下感觉写得不如此作者写得好:http://www.jianshu.com/p/da9e193e8b03 前言:EventBus出来已经有一段时间了,github上面也有很多开源 ...

  2. BS模式的模型结构详解

    编号:1004时间:2016年4月12日16:59:17功能:BS模式的模型结构详解 URL:http://blog.csdn.net/icerock2000/article/details/4000 ...

  3. Vmware在NAT模式下网络配置详解

    Vmware在NAT模式下网络配置详解 Linux中的网络配置对于接触Linux不久的小白菜来说,还是小有难度的,可能是不熟悉这种与windows系列迥然不同的命令行操作,也可能是由于对Linux的结 ...

  4. mybatis中的mapper接口文件以及example类的实例函数以及详解

    ##Example example = new ##Example(); example.setOrderByClause("字段名 ASC"); //升序排列,desc为降序排列 ...

  5. 实例-sprintf() 函数详解-输出格式转换函数

    Part1:实例 $filterfile = basename(PHP_SELF, '.php'); if (isset($_GET['uselastfilter']) && isse ...

  6. curl库pycurl实例及参数详解

    pycurl是功能强大的python的url库,是用c语言写的,速度很快,比urllib和httplib都快. 今天我们来看一下pycurl的用法及参数详解 常用方法: pycurl.Curl() # ...

  7. Android Developer -- Bluetooth篇 开发实例之四 API详解

    http://www.open-open.com/lib/view/open1390879771695.html 这篇文章将会详细解析BluetoothAdapter的详细api, 包括隐藏方法, 每 ...

  8. MyBatis的Mapper接口以及Example的实例函数及详解

    来源:https://blog.csdn.net/biandous/article/details/65630783 一.mapper接口中的方法解析 mapper接口中的函数及方法 方法 功能说明 ...

  9. MyBatis逆向工程中的Mapper接口以及Example的实例函数及详解

    一.mapper接口中的方法解析 mapper接口中的函数及方法 方法 功能说明 int countByExample(UserExample example) thorws SQLException ...

随机推荐

  1. network embedding 需读论文

    Must-read papers on NRL/NE. github: https://github.com/nate-russell/Network-Embedding-Resources NRL: ...

  2. python 动态导入模块、断言

    断言: 类似与判断,后面的程序依赖前面的,可以加一个断言,断言成功继续执行.断言失败报错停止执行. a = 'abc' assert type(a) is str print('yes') asser ...

  3. EL表达式的内置对象

    在EL表达式中,无需创建就可以使用的对象称之为EL隐藏(隐含.内置)对象.在EL中一共有11个隐藏对象,它们都与Map相似.其中10是Map,一个是 PageContext. 参数隐藏对象 这些隐藏对 ...

  4. Windows 消息框架: SDK教程

    关键字:WindowsSDK 消息机制 http://www.codeproject.com/Articles/599/Windows-Message-Handling-Part-3 Handling ...

  5. web Worker基本使用

    web worker 使用 web worker 是现代浏览器具有的可以处理密集型任务非常便利的解决方案,众所周知,JavaScript是单线程的(一个JavaScript引擎实例只能占用一个线程,线 ...

  6. SQL 创建自定义方法,匹配正则

    C#代码 using System.Text.RegularExpressions; public class FunctionRegex { [Microsoft.SqlServer.Server. ...

  7. Mysql事务级别 (二)

    事务分为4个等级: 1.read uncommitted(未提交读)     :无法避免脏读.不可重复读.虚读(幻读) 2.read committed (提交读)        :可以避免脏读 3. ...

  8. Nginx-php-mysql

    1.依赖包 yum -y install pcre* openssl*2.phprpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpmyum i ...

  9. Opencv4android的Android Studio环境配置及项目实例下载

    因为软件竞赛的项目会用到Opencv for Android,所以就研究了一下如何在Android Studio上配置Opencv4Android 环境概述: Android Studio 2.3 O ...

  10. where are you going ? 反序为:going you are where

    一个反序小算法,就是首尾替换,生成新的反序后的数组