核心还是反射,注解相关的好像都需要通过反射去处理
实现思路:
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
}