zoukankan      html  css  js  c++  java
  • 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);
        }
    
    }

       

  • 相关阅读:
    我用到的存储过程
    yii2图片处理扩展yii2-imagine的使用
    yii2——自定义widget
    YII2之 Scenario
    PHP获取某月天数
    docker版wordpress
    RBAC中 permission , role, rule 的理解
    mysql开启远程连接
    windows系统和ubuntu虚拟机之间文件共享——samba
    php生成随机字符串
  • 原文地址:https://www.cnblogs.com/shu94/p/13397900.html
Copyright © 2011-2022 走看看