事件总线模式是一种广泛运用于安卓开发之中的一种软件架构模式,而事件总线模式在安卓开发中最广泛的应用莫过于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. 栈帧示意图:stack pointer、frame pointer

    更多参考:http://www.embeddedrelated.com/usenet/embedded/show/31646-1.php 一: The calling convention descr ...

  2. spring----spring中的注解@service等的作用

    service  是有用的相当于 xml配置中得bean  id = service  也可以不指定 不指定相当于 bean id =  com. service.service 就是这个类的全限定名 ...

  3. asyncio标准库2 Hello Clock

    如何调度协程,并发运行 asyncio.gather方法可以聚合协程or future def gather(*coros_or_futures, loop=None, return_exceptio ...

  4. js实现base64编码与解码(原生js)

    一直以来很多人使用到 JavaScript 进行 base64 编码解码时都是使用的 Base64.js,但事实上,浏览器很早就原生支持 base64 的编码与解码了 以前的方式 编码: <ja ...

  5. php配置优化-生产环境应用版

    [global] error_log = log/php-fpm.log log_level = warning emergency_restart_threshold = 10 emergency_ ...

  6. JS检查输入项是否为手机号码或者固话号码的正则表达式

    var reg = /^((0\d{2,3}-\d{7,8})|(1[34578]\d{9}))$/; //校验手机号和固定电话 if ( !reg.test(shop_tel) || check_e ...

  7. tensorflow 模型不兼容

    [ERROR] [1533570199.196157]: bad callback: <bound method TLDetector.image_cb of <__main__.TLDe ...

  8. python接口测试-项目实践(五) 实际结果与预期结果对比之 接口对比

    五 与开发接口对比 1 分别将三个接口封装成三个函数,传入接口参数,返回提取并处理后的各字段. 拼接字符串作为单独的函数. def api_1(code): 发送请求获取响应 提取响应数据 响应数据转 ...

  9. IDEA tomcat热部署方法及乱码问题解决

    在项目开发过程中,我们一般希望在修改完代码之后不重启项目即可提现出修改的结果,那么热部署项目就显得十分必要了.在idea中将项目热部署至tomcat中的方法如下: 首先打开tomcat配置界面,在se ...

  10. Reverse Polish notation

    Reverse Polish notation is a notation where every operator follows all of its operands. For example, ...