生活案例
把Boss直聘比作EventBus。
Boss直聘中维护一个总表,键是企业,值是该企业需要招聘的岗位列表,这个概念很重要,一定要搞清楚。
对应到EventBus:
- 总表:名为METHOD_CACHE的Map,
- 企业:Activity的Class,
- 岗位列表:List<SubscriberMethod>
- 岗位:SubscriberMethod,也就是我们定义的接收方法的信息
岗位 SubscriberMethod :
/**
* 职位
*/
public class SubscriberMethod {
//职位要做什么事情
private Method method;
//室内还是室外
private ThreadMode threadMode;
//工作岗位类型
private Class<?> eventType;
public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
}
public Method getMethod() {
return method;
}
public ThreadMode getThreadMode() {
return threadMode;
}
public Class<?> getEventType() {
return eventType;
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MyBusEvent event) {
Log.i(TAG,"onMessageEvent接收到数据 = " + event.message);
}
- method对应的是onMessageEvent
- eventType对应的是MyBusEvent
这两个对应关系也很重要,要搞清楚。
METHOD_CACHE的定义如下:
//总表:METHOD_CACHE
//Class<?>对应阿里巴巴,List对应阿里巴巴中的所有职位
private Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new HashMap<>();
注册:将该企业到Boss直聘上注册填写岗位信息
EventBus.getDefault().register(this);
发送事件:求职者搜索岗位
EventBus.getDefault().post( new MyBusEvent("fujunyang"));
简单总结:
- 总表:名为METHOD_CACHE的Map,
- 企业:Activity的Class,
- 岗位列表:List<SubscriberMethod>
- 岗位:SubscriberMethod,
注册:一个注册register,就是将该企业的所有岗位,添加到总表中。
总表(METHOD_CACHE)的键是企业(Activity),值是该企业所有岗位(List<SubscriberMethod>)。
发送事件:循环总表,在某个循环中,找出该企业对应的所有岗位。再循环所有岗位,找到求职者搜索的岗位是否和该企业所有岗位匹配。如果匹配就通过反射调用方法(method是onMessageEvent,参数是具体的Activity和MyBusEvent)
获取EventBus对象
使用单例,直接复用了EventBus的源代码
public class EventBus {
public static String TAG = "EventBus";
static volatile EventBus defaultInstance;
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
注册
EventBus通过如下实现注册
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
注册的具体实现如下:
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
//如果不为空,说明阿里巴巴注册过,不需要再次注册
if (subscriberMethods == null) {
//如何寻找能够接收事件的方法??通过注解
subscriberMethods = getSubscriberMethods(subscriber);
METHOD_CACHE.put(subscriberClass, subscriberMethods);
}
}
通过企业(Activity的Class)作为键,去总表METHOD_CACHE中获取所有该企业的职位subscriberMethods。
如果subscriberMethods为null,说明该企业还没有注册过,我们才去注册。如果注册过了,就不再注册。
private List<SubscriberMethod> getSubscriberMethods(Object subscriber) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>();
Class clazz = subscriber.getClass();
//getDeclaredMethod获取的是类自身声明的所有方法,包含public、protected、private方法
Method[] methods = clazz.getDeclaredMethods();
//需要将父类的注解也找出来,比如BaseActivity中可能也添加了注解
while (clazz != null) {
String clazzName = clazz.getName();
//遇到系统类,直接跳出循环,不再去寻找
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") ||
clazzName.startsWith("android.") || clazzName.startsWith("androidx.")) {
break;
}
for (Method method : methods) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation == null) {
continue;
}
//检测方法 是否符合规范
Class[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1) {
throw new RuntimeException("EventBus只能接收一个参数");
}
Class<?> eventType = parameterTypes[0];
ThreadMode threadMode = subscribeAnnotation.threadMode();
SubscriberMethod subscriberMethod = new SubscriberMethod(method, eventType, threadMode);
subscriberMethods.add(subscriberMethod);
}
clazz = clazz.getSuperclass();
}
return subscriberMethods;
}
发送事件
//发送事件
//事件对应岗位,假设现在event是android岗位
public void post(Object event) {
// 找哪个activity需要接收
// 遍历总表,分别查看阿里和腾讯是否招android岗位
Set<Class<?>> set = METHOD_CACHE.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
//拿到公司,假设当前拿到的是阿里
Class<?> subscriberClass = (Class<?>) iterator.next();
//subscriberMethods是阿里的所有岗位集合
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//判断这个方法是否应该接收事件
//判断阿里的岗位中是否有招android岗位的
if (subscriberMethod.getEventType().isAssignableFrom(event.getClass())) {
// invoke(subscriberMethod, subscriberClass, event);
Method method = subscriberMethod.getMethod();
try {
//通过反射调用方法
method.invoke(subscriberClass.newInstance(), event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
在MainActivity中使用:
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MyBusEvent event) {
Log.i(TAG,"onMessageEvent接收到数据 = " + event.message);
// textView.setText(event.message);
// Toast.makeText(MainActivity.this, event.message, Toast.LENGTH_SHORT).show();
}
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
最简单的说:就是通过注解,反射调用对应的方法