EventBus (发布者和订阅者)
前言
小项目页面间、线程间、模块间,通信一般使用:公共变量、Intent、Handler、Broadcast,接口等等。。
当项目越来越复杂时,使用这些通信方式之后,代码量大,逻辑错终复杂,高度耦合。为了解决这个大问题,然后就诞生了这个框架。
官网示例调用代码:
EventBus in 3 steps
-
Define events:
public static class MessageEvent { /* Additional fields if needed */ }
-
Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:
@Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) {/* Do something */};
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
@Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { super.onStop(); EventBus.getDefault().unregister(this); }
-
Post events:
EventBus.getDefault().post(new MessageEvent());
自定义Event事件
订阅者接收消息注册:EventBus.getDefault().register()(一般在onCreate中注册)
订阅者取消订阅注册:EventBus.getDefault().unregister();(一般在onDestory中解除注册)
发布者发送消息:EventBus.getDefault().post(event)
订阅者接收消息:1、注解 2、主线程 3、event中取消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent evnt){}
图解:
image.png
扩展:
onEvent:发送者在哪个线程发送的,该方法也在哪个线程中处理事件
onEventMainThread:不管发送者在哪个线程发送的,该方法都会在主线程中处理事件
onEventBackgroundThread:如果发送者是在子线程发送的,那么该方法也在同一个子线程处理事件,如果发送者是在主线程,那么该方法在一个线程池中处理事件
onEventAsync:不管发送者在哪个线程发送的,该方法都在线程池中执行
原理:
先从注册开始看,
1、EventBus.getDefault().register(this);将Activity.this传递进EventBus当中,里面通过反射,获取到包含@Subscribe 注解的函数,
2、筛选onEvent开头的方法,获取方法的权限修饰符,必须是public,然后获取函数所需参数数组,
3、通过把方法名,方法形参,线程模型封装成一个SubscriberMethod添加进集合里,
3、然后遍历集合中当前订阅者的所有订阅方法,通过订阅方法参数的字节码,创建订阅者,优先级处理,事件类型处理
再看Post:
1、获取当前线程的队列,将event添加到队列里;
2、通过event拿到事件的字节码,注意event是支持继承的,会获取到事件的父类和接口的字节码到集合中;
3、然后通过该事件字节码获取所有的订阅者。
4、根据不同的线程模型调用不同的方法:
通过反射调用订阅者订阅方法
handler发送消息
在线程池发送消息(包含异步或者后台两种)
网友评论