EventBus解析并实现手写EventBus

    xiaoxiao2023-11-08  178

    前言

    其实在我们开发当中需要应用组件与后台线程间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过Handler或者是广播通知UI,而两个Fragment之家可以通过Listener进行通信等等。当我们的项目越来越复杂,使用Intent、Handler、Broadcast进行模块间通信、模块与后台线程进行通信时,代码量大,而且高度耦合;最近公司正在做了一款项目是要求模块化来做,前期考虑是想用阿里的ARouter实现模块间的跳转和传值,因为我们公司App设计是一个Activity其别的页面都是显示用Fragment去展示的,考虑到返回容器的处理觉得ARouter不适合,就选择了EventBus来实现模块间的跳转和传值,下面带大家了解下EventBus。

    什么是EventBus?

    EventBus是Android和Java的发布/订阅事件总线; 事件总线是对发布–订阅模式的一种实现。他是一种集中式事件处理机制,允许不同的组件之间彼此通信而不需要相互依赖,达到解耦的目的。

    三要素

    一:Event 事件; 二:Subscriber 事件订阅者; 三:Publisher 事件发布者;

    四种线程模型

    POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程; MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作; BACKGROUND 表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程; ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作;

    EventBus优点

    一: 代码简单,快; 二:jar包小; 三:Activity、Fragment以及线程间通信优秀; 四:稳定;

    上面简单了解了一下EventBus下面我们就手动实现下:
    第一步我们先注册,为了区别官方我们定义MyEventBus
    MyEventBus.getDefault().register(this);
    二:定义一个实现数据回调的方法
    @Subscrible(threadMode = ThreadMode.MAIN)//线程为主线程 public void getMessage(EventBean eventBean){ Toast.makeText(MainActivity.this,eventBean.toString(),Toast.LENGTH_SHORT).show(); Log.e("main", eventBean.toString()); }
    三:我们先创建一个注解处理器
    @Target(ElementType.METHOD)//注解到方法上面 @Retention(RetentionPolicy.RUNTIME)//定义运行时 public @interface Subscrible { // ThreadMode threadMode() default ThreadMode.MAIN; }
    四:写个枚举来区分线程
    public enum ThreadMode { MAIN, BACHGROUND }
    五:接收方法参数为bean类
    public class EventBean { private String name; private String msg; public EventBean(final String name, final String msg) { this.name = name; this.msg = msg; } @Override public String toString() { return "EventBean{" + "name='" + name + '\'' + ", msg='" + msg + '\'' + '}'; } }
    六:开始来写核心代码
    public class MyEventBus { //定义一个容器来存放方法 private Map<Object, List<SubscribleMethod>> cacheMap; private Handler mHandler; private static volatile MyEventBus instance; private MyEventBus() { cacheMap = new HashMap<>(); mHandler = new Handler(); } public static MyEventBus getDefault() { if (instance == null) { synchronized (MyEventBus.class) { if (instance == null) { instance = new MyEventBus(); } } } return instance; } // 在这个方法中去判断所有当前类的所有方法 public void register(Object obj) { // 首先在map集合取当前类的集合 List<SubscribleMethod> list = cacheMap.get(obj); if (list == null) { // 定义方法取 list = findSubscribleMethods(obj); // 存到容器 cacheMap.put(obj, list); } } private List<SubscribleMethod> findSubscribleMethods(final Object obj) { // 定义一个集合 List<SubscribleMethod> list = new ArrayList<>(); // Class<?> aClass = obj.getClass(); // 可以得到当前类的所有方法 此方法获取不带父类的方法 Method[] methods = aClass.getDeclaredMethods(); // // 若是取父类的方法 用下面方法 // Method[] methods1 = aClass.getMethods(); while (aClass != null) {//此循环是向父类一层层往上找 // 找父类的时候是要先判断下是否是系统级别的父类 String name = aClass.getName(); // 判断是系统级别的名字就停止 if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) { break; } // 遍历所有方法 for (Method method : methods) { // 找到带Subscrible注解的方法, Subscrible subscrible = method.getAnnotation(Subscrible.class); if (subscrible == null) { continue; } // 获取subscrible的参数类型 Class<?>[] types = method.getParameterTypes(); // 不为空的时候就判断下带有subscrible注解的方法参数类型 if (types.length == 1) { } ThreadMode threadMode = subscrible.threadMode(); SubscribleMethod subscribleMethod = new SubscribleMethod(method, threadMode, types[0]); list.add(subscribleMethod); } // 等于父类的类 aClass =aClass.getSuperclass(); } return list; } // 发送evengtbus的方法 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) {//遍历 // 判断方法的参数是否相等 if (subscribleMethod.getType().isAssignableFrom(type.getClass())){ // 判断下线程 switch (subscribleMethod.getThreadMode()){ 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; case BACHGROUND: //后续添加 break; } } } } } // 是一个回调的方法 private void invoke(final SubscribleMethod subscribleMethod, final Object obj, final Object type) { Method method = subscribleMethod.getMethod(); try { method.invoke(obj,type); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }
    总结

    上面代码主要是实现一个简单的EventBus实现数据传递,因为源码里面还有好多方法后续会陆续添加,也希望更多的小伙伴多多提下意见,共同进步下面给大家提供本人github地址本人已经上传望大家共同改进。

    本篇github传送门
    最新回复(0)