通过对EventBus源码分析,剥离出核心api的实现:
1、EventBus.getDefault():EventBus的单例实现,保证全局只有一个EventBus类实例;
2、register():事件订阅者的注册
3、post():消息的发送
4、unregister():事件订阅者的注销
注:不考虑不同线程之间的消息发送,不考虑发送消息的优先级以及其他防止内存泄漏的优化处理等。
代码实现:
注解类:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventM {
}
记录一个类以及对应的所有方法的类:目的是方便遍历每个类中的方法
import java.lang.reflect.Method;
public class ObjAndMethod {
Method method;
Object object;
public ObjAndMethod(Method method, Object object) {
this.method = method;
this.object = object;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ObjAndMethod) {
ObjAndMethod objAndMethod = (ObjAndMethod) obj;
return method.equals(objAndMethod.method) && object == objAndMethod.object;
} else {
return false;
}
}
@Override
public int hashCode() {
return method.hashCode() + object.hashCode();
}
}
核心逻辑类:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EventS {
private volatile static EventS instance;
//存放发送参数类型 与 注册类和注解方法 的对应关系
private Map<Class<?>, List<ObjAndMethod>> paramAndObjMethedMap;
//存放注册类 与 所有注解方法参数class 的对应关系 , 设计目的:方便paramAndObjMethedMap移除
private Map<Object, List<Class<?>>> objAndParamMap;
private EventS() {
paramAndObjMethedMap = new HashMap<>();
objAndParamMap = new HashMap<>();
}
public static EventS getInstance() {
if (instance == null) {
synchronized (EventS.class) {
if (instance == null) {
instance = new EventS();
}
}
}
return instance;
}
<T> void register(T t) {
Class<?> subscriberClass = t.getClass();
//获取所有注册类中的方法
Method[] methods = subscriberClass.getDeclaredMethods();
for (Method method : methods) {
//获取注册类中 被EventM 注解过的方法
EventM eventM = method.getAnnotation(EventM.class);
if (eventM != null) {
//将注册类的相关信息添加到 paramAndObjMethedMap
Class<?> paramClass = method.getParameterTypes()[0];
List<ObjAndMethod> objAndMethodList = paramAndObjMethedMap.get(paramClass);
if (objAndMethodList == null) {
objAndMethodList = new ArrayList<>();
paramAndObjMethedMap.put(paramClass, objAndMethodList);
}
ObjAndMethod objAndMethod = new ObjAndMethod(method, t);
objAndMethodList.add(objAndMethod);
将注册类的相关信息添加到 objAndParamMap
List<Class<?>> classList = objAndParamMap.get(t);
if (classList == null) {
classList = new ArrayList<>();
objAndParamMap.put(t, classList);
}
classList.add(paramClass);
}
}
}
<T> void unregister(T t) {
List<Class<?>> classList = objAndParamMap.get(t);
if (classList != null) {
for (Class<?> aClass : classList) {
List<ObjAndMethod> objAndMethodList = paramAndObjMethedMap.get(aClass);
if (objAndMethodList != null) {
int size = objAndMethodList.size();
for (int i = 0; i < size; i++) {
ObjAndMethod objAndMethod = objAndMethodList.get(i);
if (objAndMethod.object == t){
objAndMethodList.remove(i);
i--;
size--;
}
}
}
}
}
}
<T> void post(T t) {
List<ObjAndMethod> objAndMethodList = paramAndObjMethedMap.get(t.getClass());
if (objAndMethodList != null){
for (ObjAndMethod objAndMethod : objAndMethodList) {
try {
objAndMethod.method.invoke(objAndMethod.object,t);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
使用到的知识点:
java反射;
泛型;
注解;
个人理解:源码设计的巧妙之处在于核心类中的两个集合,通过两个Map集合,轻松实现对所有类及其方法的遍历查询,理解了这两个集合就理解了EventBus的核心工作源码,至于其他的功能都是在此基础上的延伸,算是锦上添花吧。