android架构师之路——模仿eventbus

 

 

EventBus使用

1、eventbus简介

     eventbus是Android事件发布-订阅总线,简化了活动片段、线程、服务等之间的通信,代码更少,质量更好,可以避免由于使用广播通信而带来的诸多不便。具体使用可以参考:https://github.com/greenrobot/EventBus,我这里主要是简单讲解eventBus的代码逻辑思想,以及自己简单实现一个EventBus

2、Subscribe 介绍

@Subscribe采用运行时注解,且注解只能用在函数上,默认的threadmode为posting

3、threadMode介绍

POSTING默认的模式,开销最小的模式,因为声明为POSTING的订阅者会在发布的同一个线程调用,发布者在主线程那么订阅者也就在主线程,反之亦,避免了线程切换,如果不确定是否有耗时操作,谨慎使用,因为可能是在主线程发布
MAIN主线程调用,视发布线程不同处理不同,如果发布者在主线程那么直接调用(非阻塞式),如果发布者不在主线程那么阻塞式调用
MAIN_ORDERED和MAIN差不多,主线程调用,和MAIN不同的是他保证了post是非阻塞式的(默认走MAIN的非主线程的逻辑,所以可以做到非阻塞)
BACKGROUND在子线程调用,如果发布在子线程那么直接在发布线程调用,如果发布在主线程那么将开启一个子线程来调用,这个子线程是阻塞式的,按顺序交付所有事件,所以也不适合做耗时任务,因为多个事件共用这一个后台线程
ASYNC在子线程调用,总是开启一个新的线程来调用,适用于做耗时任务,比如数据库操作,网络请求等,不适合做计算任务,会导致开启大量线程

 4、register介绍

通过getDefault获取EventBus实例,这是一条默认的事件总线,通过单例模式实现,其构造函数是Public的也可以通过new的形式来创建多条事件总线

 

  

register方法 

    /**
     * 注册
     */
    public void register(Object subscriber) {
        Class<?> aClass = subscriber.getClass();
        //从缓存中读取
        List<SubscribleMethod> subscribleMethods = cacheMap.get(subscriber);
        //缓存中没有
        if (null == subscribleMethods) {
            subscribleMethods = getSubscribleMethods(subscriber);
            cacheMap.put(subscriber, subscribleMethods);
        }
    }

 getSubscribleMethods方法

    /**
     * 遍历接收事件的方法
     *
     * @param subscriber
     * @return
     */
    private List<SubscribleMethod> getSubscribleMethods(Object subscriber) {

        List<SubscribleMethod> list = new ArrayList<>();
        Class<?> aClass = subscriber.getClass();

        while (aClass != null) {
            //判断分类是在那个包下,(如果是系统的就不需要)
            String name = aClass.getName();
            if (name.startsWith("java.")
                    || name.startsWith("javax.")
                    || name.startsWith("android.")
                    || name.startsWith("androidx.")) {
                break;
            }
            //对象表示的类或接口声明的所有方法
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                //获取我们自己定义的标签
                Subscribe annotation = declaredMethod.getAnnotation(Subscribe.class);
                if (annotation == null) {
                    continue;
                }

                //获得方法参数类型
                Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
                //eventbus 是能有一个参数
                if (parameterTypes.length != 1) {
                    throw new RuntimeException("eventbusz只能接收一个参数");
                }

                //符合要求的
                ThreadMode threadMode = annotation.threadMode();
                SubscribleMethod subscribleMethod = new SubscribleMethod(declaredMethod,threadMode,parameterTypes[0]);
                list.add(subscribleMethod);

            }

            //获取父类  activity---->baseActivity----->
            aClass = aClass.getSuperclass();
        }
        return list;
    }

5、post简介

我这里就只处理了MAIN、ASYNC、POSTING线程之间的切换,遍历前面register的activity中的所有@Subscribe方法,在post方法中根据threadMode线程来切换相应的线程

 

  /**
     * 发送数据
     * @param obj
     */
    public void post(final Object obj) {
        Set<Object> objects = cacheMap.keySet();
        Iterator<Object> iterator = objects.iterator();
        while (iterator.hasNext()){
            //拿到注册类
            final Object next = iterator.next();
            //获取类中所有添加注解的方法
            List<SubscribleMethod> subscribleMethods = cacheMap.get(next);
            for (final SubscribleMethod subscribleMethod : subscribleMethods) {
                if (subscribleMethod.getEventType().isAssignableFrom(obj.getClass())){
                    switch (subscribleMethod.getThreadMode()){
                        case MAIN:
                            //如果接收方法在主线程执行的情况
                            if(Looper.myLooper() == Looper.getMainLooper()){
                                invoke(subscribleMethod, next, obj);
                            } else {
                                //post方法执行在子线程中,接收消息在主线程中
                                handler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        invoke(subscribleMethod, next, obj);
                                    }
                                });
                            }
                            break;
                        //接收方法在子线程种情况
                        case ASYNC:
                            //post方法执行在主线程中
                            if(Looper.myLooper() == Looper.getMainLooper()){
                                executorService.execute(new Runnable() {
                                    @Override
                                    public void run() {
                                        invoke(subscribleMethod, next, obj);
                                    }
                                });
                            } else {
                                //post方法执行在子线程中
                                invoke(subscribleMethod, next, obj);
                            }
                            break;

                        case POSTING:
                            break;
                    }
                }
            }
        }
    }

 

   /**
     * 执行方法
     * @param subscribleMethod
     * @param next
     * @param obj
     */
    private void invoke(SubscribleMethod subscribleMethod, Object next, Object obj) {
        Method method = subscribleMethod.getMethod();
        try {
            method.invoke(next, obj);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

 6、unregister方法

   /**
     * 取消注册
     */
    public void unregister(Object subscriber) {
        List<SubscribleMethod> subscribleMethods = cacheMap.get(subscriber);
        if (subscribleMethods!=null){
            cacheMap.remove(subscriber);
        }
    }

总结

这里简单实现了eventBus的register、post、unregister方法,具体代码下载地址:demo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值