• Android EventBus


    当我们进行项目开发的时候,往往是需要应用程序的各组件、组件与后台线程间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过Handler或者是广播通知UI,而两个Fragment之家可以通过Listener进行通信等等。当我们的项目越来越复杂,使用Intent、Handler、Broadcast进行模块间通信、模块与后台线程进行通信时,代码量大,而且高度耦合。

    Event 事件。它可以是任意类型。

    Subscriber 事件订阅者。在EventBus3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。

    Publisher 事件的发布者。我们可以在任意线程里发布事件,一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。


    自己从零开始写EventBus
    创建EventBus
    /创建Eventbus
        public static EventBus getDefault() {
            if(instance==null)
            {
               synchronized (EventBus.class){
                   if (instance==null)
                   {
    
                       instance=new EventBus();
                   }
               }
            }
            return instance;
        }

    注册

    //注册
        public void register(Object obj) {
           List<SubscribleMethod> list =cachemap.get(obj);
           if(list==null)
           {
             list =findSubscribleMethod(obj);
                cachemap.put(obj,list);
    
           }
        }

    通信之间的寻找通过注解的方法寻找,这里为默认方式

    @Subcrible(threadMode= ThreadMode.MAIN)
    、

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Subcrible {

    ThreadMode threadMode() default ThreadMode.MAIN;

    }
    
    
    Subcrible的各种状态
    package com.example.eventbus;
    
    import java.lang.reflect.Method;
    
    public class SubscribleMethod {
    
    
        //回调方法
        private Method mMethod;
        //线程模式
        private ThreadMode mthreadMode;
    
        //方法中的参数
        private  Class<?> type;
    
        public SubscribleMethod(Method mMethod, ThreadMode mthreadMode, Class<?> type) {
            this.mMethod = mMethod;
            this.mthreadMode = mthreadMode;
            this.type = type;
        }
    
        public void setmMethod(Method mMethod) {
            this.mMethod = mMethod;
        }
    
        public void setMthreadMode(ThreadMode mthreadMode) {
            this.mthreadMode = mthreadMode;
        }
    
        public Method getmMethod() {
            return mMethod;
        }
    
        public ThreadMode getMthreadMode() {
            return mthreadMode;
        }
    
        public Class<?> getType() {
            return type;
        }
    
        public void setType(Class<?> type) {
            this.type = type;
        }
    
    
    }

    通信寻找注解的方法

      private List<SubscribleMethod> findSubscribleMethod(Object obj) {
             List<SubscribleMethod> list=new ArrayList<>();
             Class< ?> clazz =obj.getClass();
             Method[] methods =clazz.getDeclaredMethods();
             while (clazz!=null)
             {
                 //找父类的时候需要先判断一下是否系统级别的父类
                 String name=clazz.getName();
                 if(name.startsWith("java.")||name.startsWith("javax.")
               ||name.startsWith("android"))
                 {
                     break;
                 }
                 for (Method method:methods)
                 {
                     //找到带有Subcrible 注解的方法
                     Subcrible subcrible=method.getAnnotation(Subcrible.class);
                     if (subcrible==null)
                     {
                         continue;
                     }
                     //判断subscrible 注解的方法中的参数类
                     Class<?>[] type=   method.getParameterTypes();
                     if(type.length!=1)
                     {
                         Log.e("TAG", "eventBus only accept one para  " );
                     }
                     ThreadMode threadMode=subcrible.threadMode();
                     SubscribleMethod subscribleMethod=new SubscribleMethod(method,threadMode,type[0]);
                     list.add(subscribleMethod);
                 }
                       clazz= clazz.getSuperclass();
             }
    
            return list;
        }
    
        public void post(final Object type) {
    
           //直接循环 Map里的方法 ,找到相对得然后回调
            Set<Object> set =cachemap.keySet();
            Iterator<Object> iterator=set.iterator();
            while (iterator.hasNext())
            {
                final Object  obj =iterator.next();
                List<SubscribleMethod>list=cachemap.get(obj);
                for (final SubscribleMethod subscribleMethod:list){
                    //a(if 条件得对象)对象所对应得类信息是不是b if条件后面得对象对象所对应得接口或者父类
                    if (subscribleMethod.getType().isAssignableFrom(type.getClass()))
                    {
                        switch (subscribleMethod.getMthreadMode())
                        {
                            case MAIN:
                                //主线程 -主线程
                                if (Looper.myLooper()==Looper.getMainLooper())
                                {
                                    invoke(subscribleMethod,obj,type);
                                }
                                else {
                                    //子线程 -主线程
                                    mHandler.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            invoke(subscribleMethod,obj,type);
                                        }
                                    });
                                }
                                break;
    
                        }
    
    
    
                    }
    
                }
    
    
            }
        }
    
        private void invoke(SubscribleMethod subscribleMethod, Object obj, Object type) {
           Method method=subscribleMethod.getmMethod();
         try {
             method.invoke(obj,type);
         }catch (IllegalAccessException e)
         {
             e.printStackTrace();
         }
         catch (InvocationTargetException e)
         {
             e.printStackTrace();
         }
    
    
        }
    }

    运行起来的效果如下

     这里是源码包分享

    链接:https://pan.baidu.com/s/1CnTNCndQHizktb4e338BnA
    提取码:vcvx
    复制这段内容后打开百度网盘手机App,操作更方便哦

  • 相关阅读:
    python之路day10命名空间和作用域、函数嵌套,作用域链、闭包
    20200719 千锤百炼软工人第十四天
    20200720 千锤百炼软工人第十五 天
    JavaScript中基本数据类型和引用数据类型的区别
    js 经纬度坐标格式化 度分秒转度 度转度分秒
    export ,export default 和 import 区别 以及用法
    10月28日学习日志
    10月20日学习日志
    10月29日学习日志
    10月27日学习日志
  • 原文地址:https://www.cnblogs.com/xujunjia/p/11497226.html
Copyright © 2020-2023  润新知