注解实现EventBus功能

核心还是反射,注解相关的好像都需要通过反射去处理

实现思路:

1. 定义一个Map集合存放注册EventBus的对象,以及该对象注册的事件方法和参数

2.注册时去遍历获取该对象符合条件的注解属性,并存到步骤1的集合中

3.发送事件时,遍历步骤1创建的集合,判断发送事件的Object对象类型,如果集合中有该对象类型或者该对象类型的父类,则认为是匹配的,这时候的key就是实际注册的Activity等对象,根据key拿到相应的方法等属性,通过反射去调用该方法

4.解除注册,只需要移除相应对象即可(当然不移除会导致内存泄露)

 

先定义一个方法注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.MAIN;
}

public enum ThreadMode {
    MAIN,
    ASYN
}

再定义一个对象去存储注册信息

public class MethodModes {

    public Method method;
    public Class type;
    public ThreadMode threadMode;

    public MethodModes(Class type, Method method,ThreadMode threadMode) {
        this.type = type;
        this.method = method;
        this.threadMode = threadMode;
    }
    
}

定义一个单例的EventBus

public class EventBus {

    private static volatile EventBus instance;
    private static HashMap<Object, List<MethodModes>> cacheMap = new HashMap<>();
    private Handler mHandler = new Handler(Looper.getMainLooper());
    private ExecutorService executorService = Executors.newCachedThreadPool();

    public static EventBus getDefault() {
        if (instance == null) {
            instance = new EventBus();
        }
        return instance;
    }
}

定义一个方法去获取注册对象中匹配的方法

 private List<MethodModes> getMethods(Object object) {
        Class mClass = object.getClass();
        Method methods[] = mClass.getDeclaredMethods();
        List<MethodModes> list = new ArrayList<>();
        for (Method method : methods) {
            Subscribe subscribe = method.getAnnotation(Subscribe.class);
            if (subscribe != null) {
                ThreadMode threadMode = subscribe.threadMode();
                Class<?>[] types = method.getParameterTypes();
                if (types.length != 1) continue; //只匹配一个参数的
                MethodModes mMode = new MethodModes(types[0], method, threadMode);
                list.add(mMode);
            }
        }
        return list;
    }

定义发送事件的方法,只要发送的是方法定义的属性类本身及其子类,都可以发送

public void post(Object object) {
        Set<Object> keyset = cacheMap.keySet();
        Iterator<Object> iterator = keyset.iterator();
        while (iterator.hasNext()) {
            Object key = iterator.next();
            List<MethodModes> modes = cacheMap.get(key);
            for (MethodModes item : modes) {
                if (item.type.isAssignableFrom(object.getClass())) { //和instance of相反 后者需要是前者本身或者子类
                    switch (item.threadMode) {
                        case MAIN:
                            mHandler.post(() ->
                                    invokePost(item, key, object));
                            break;
                        case ASYN:
                            executorService.execute(new Runnable() {
                                @Override
                                public void run() {
                                    invokePost(item, key, object);
                                }
                            });
                            break;
                    }
                }
            }
        }
    }

  private void invokePost(MethodModes item, Object key, Object type) {
        try {
            Method method = item.method;
            method.setAccessible(true);
            method.invoke(key, type);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

最后是注册和解注册方法

  public void register(Object object) {
        if (cacheMap.get(object) == null) {
            cacheMap.put(object, getMethods(object));
        }
    }

    public void unRegister(Object object) {
        if (cacheMap.get(object) != null) {
            cacheMap.remove(object);
        }
    }

使用方法和EventBus类似

 @Subscribe(threadMode = ThreadMode.MAIN)
    public void receive(EventMode msg) {
        //TODO
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值