EventBus框架的模型理解
通常使用一个框架,最好要能理解它的架构模型。eventbus作为常见的组件通信框架,对开发者来说并不陌生,而且它比较容易上手,架构并不复杂。今天谈谈对使用它的一些简单理解。
我们常常把观察者模式等同于订阅者模式,在eventbus的使用中,注册、注销这些字面意思显现的方法也会提醒你,我们这个框架就是订阅者模式。如果你对这个模式理解不是很清楚,不要紧,换换思路,会有更有意思的答案。eventbus中文名为事件总线,总线又是计算机里面的概念,它是计算机各个部件传输信息的公共连接线路。如图:张村、李县、王湾就是各个部件,张村到李县,李县到王湾都得走总线这条路。推广到事件总线,每一个部件就是安卓中的组件,activity或者fragment,它们是事件的载体。当fragment1的event1想到发消息给fragment2的event1,为了降低组件的耦合性,eventbus作为传输信息的中间层,通过它管理的一系列集合,准确地找到目标。eventbus的关键就是构建这个集合。
通过一个例子,看看evenbus怎么构建方法、组件对象的集合关系。
这个方法的封装对象,通过注解可以构造出这个对象
public class SubscribeMethod {
Method method;
ThreadMode threadMode;
Class<?> eventType;
public SubscribeMethod(Method method, ThreadMode threadMode, Class<?> eventType) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
}
}
一个方法通常需要知道它属于哪个对象,以便之后通过反射来调用它,所以可以在上面的对象上在封装成一层。
public class Subscroption {
SubscribeMethod subscribeMethod;
Object platform;
public Subscroption(SubscribeMethod subscribeMethod, Object platform) {
this.subscribeMethod = subscribeMethod;
this.platform = platform;
}
}
注解的定义可以把源码搬过来,以下是根据实现注册、发送、解绑的简单版eventbus。
public class EventBus {
private static EventBus eventBus;
private EventBus(){}
public static EventBus getDefault(){
if (eventBus == null){
eventBus = new EventBus();
}
return eventBus;
}
//key 为注解方法参数的class对象, value为来自所有装载对象(activity、fragment)用Subscribe标记的封装方法对象集合
private final Map<Class<?>, List<Subscroption>> subscriptionsByEventType = new HashMap<>();
//key为挂载对象,正如上面的图所示,一个acitivity可以当做包括了多个注解标记的event的容器,把它挂载到eventbus上,
//以后再通过解绑方法把这个容器卸载,整个过程很形象。
//value为注解方法参数的class对象,这个集合存在的意义就在于卸载。当我们传入组件对象时,它的value集合中的每一项可以
//作为上面map集合的key,进行过滤移除method封装对象。
private final Map<Object, List<Class<?>>> typesBySubscriber = new HashMap<>();
//之后我们要从这个obj的对象里找出它的带注解的方法
public void register(Object obj){
Class<?> activityClass = obj.getClass();
Method[] methodArray = activityClass.getDeclaredMethods();
List<SubscribeMethod> methodList = new ArrayList<>();
for (Method method : methodArray) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length==1){
Subscribe annotation = method.getAnnotation(Subscribe.class);
if (annotation != null) {
ThreadMode threadMode = annotation.threadMode();
methodList.add(new SubscribeMethod(method, threadMode,parameterTypes[0]));
}
}
}
for (SubscribeMethod subscribeMethod : methodList) {
subscrite(subscribeMethod,obj);
}
}
private void subscrite(SubscribeMethod method,Object obj){
Class<?> eventType = method.eventType;
Subscroption newSubscription = new Subscroption(method, obj);
List<Subscroption> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new ArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
}
subscriptions.add(subscriptions.size(), newSubscription);
List<Class<?>> classList = typesBySubscriber.get(obj);
if (classList == null) {
classList = new ArrayList<>();
typesBySubscriber.put(obj, classList);
}
classList.add(eventType);
}
public void post(Object object) {
Class<?> aClass = object.getClass();
List<Subscroption> subscroptionList = subscriptionsByEventType.get(aClass);
for (Subscroption subscroption : subscroptionList) {
try {
subscroption.subscribeMethod.method.invoke(subscroption.platform,object);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void unregister(Object object) {
List<Class<?>> classes = typesBySubscriber.get(object);
for (Class<?> aClass : classes) {
List<Subscroption> subscroptionList = subscriptionsByEventType.get(aClass);
if (subscroptionList != null) {
int size = subscroptionList.size();
for (int i=0;i<size;i++){
Subscroption subscription = subscroptionList.get(i);
if (subscription.platform == object) {
subscroptionList.remove(i);
i--;
size--;
}
}
}
}
typesBySubscriber.remove(object);
}
}