您当前的位置: 首页 > 
  • 0浏览

    0关注

    674博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

EventBus手动实现

沙漠一只雕得儿得儿 发布时间:2020-01-31 18:33:23 ,浏览量:0

0、手写EventBus运行效果:

从MainActivity跳转到SecondActivity,在第二个页面中点击“发送消息”后,在MainActivity中接受到消息并setText改变文本内容:

一、EventBus相关概念原理:

二、EventBus执行流程

三、手写eventbus,分为两大步骤 步骤一:EventBus事件注册register流程

将带有注解subscriber的方法的类放到map集合中进行缓存,遍历能够接收事件的方法

步骤二:EventBus事件post流程

1.从map集合中获取缓存的,利用EventType获取有我们注解的方法,并利用反射执行这些方法 2.切换线程方式:在主线程中切换到子线程,在子线程中切换到主线程

整体方法如下:

public class DNEventbus {
    private static DNEventbus instance = new DNEventbus();


    private Map cacheMap;

    private Handler handler;

    //线程池
    private ExecutorService executorService;

    public static DNEventbus getDefault() {
        return instance;
    }

    private DNEventbus() {
        this.cacheMap = new HashMap();
        handler = new Handler(Looper.getMainLooper());
        executorService = Executors.newCachedThreadPool();
    }


    /**
     * 注册:将带有注解subscriber的方法的类放到map集合中进行缓存
     * @param subscriber
     */
    public void register(Object subscriber) {
        Class aClass = subscriber.getClass();
        List subscribleMethods = cacheMap.get(subscriber);
        //如果已经注册,就不需要注册
        if (subscribleMethods == null) {
            subscribleMethods = getSubscribleMethods(subscriber);
            cacheMap.put(subscriber, subscribleMethods);
        }
    }

    //遍历能够接收事件的方法
    private List getSubscribleMethods(Object subscriber) {
        List list = new ArrayList();
        Class aClass = subscriber.getClass();
        //需要 subscriber ---> BaseActivity  -----> Activity
        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 method : declaredMethods) {
                DNSubscribe annotation = method.getAnnotation(DNSubscribe.class);
                if (annotation == null) {
                    continue;
                }

                //检测这个方法合不合格
                Class[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length != 1) {
                    throw new RuntimeException("eventbus只能接收一个参数");
                }

                //符合要求
                DNThreadMode dnThreadMode = annotation.threadMode();
                SubscribleMethod subscribleMethod = new SubscribleMethod(method, dnThreadMode, parameterTypes[0]);
                list.add(subscribleMethod);
            }
            aClass = aClass.getSuperclass();
        }
        return list;
    }


    //取消注册,将map集合中缓存的类删除掉
    public void unregister(Object subscriber) {
        Class aClass = subscriber.getClass();
        List list = cacheMap.get(subscriber);
        //如果获取到
        if (list != null) {
            cacheMap.remove(subscriber);
        }
    }

    /**
     * 1.从map集合中获取缓存的,利用EventType获取有我们注解的方法,并利用反射执行这些方法
     * 2.切换线程方式:在主线程中切换到子线程,在子线程中切换到主线程
     * @param obj
     */
    public void post(final Object obj) {
        Set set = cacheMap.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            //拿到注册类
            final Object next = iterator.next();

            //获取类中所有添加注解的方法
            List list = cacheMap.get(next);
            for (final SubscribleMethod subscribleMethod : list) {
                //判断这个方法是否应该接收事件
                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;
                    }

                }
            }
        }
    }

    //post后直接反射调用这个方法
    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();
        }
    }

}

项目地址:https://github.com/buder-cp/DesignPattern/tree/master/buder_DN_EventBus

关注
打赏
1657159701
查看更多评论
立即登录/注册

微信扫码登录

0.0722s