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);
    }

}

 

   

posted on 2020-07-29 16:24  荒郊野岭一根葱  阅读(184)  评论(0编辑  收藏  举报