a)定义注解类Subscribe
@Target(ElementType.METHOD) // 该注解作用在方法之上
@Retention(RetentionPolicy.CLASS) // 要在编译时进行一些预处理操作,注解会在class文件中存在
public @interface Subscribe {
// 线程模式,默认推荐POSTING(订阅、发布在同一线程)
ThreadMode threadMode() default ThreadMode.POSTING;
// 是否使用粘性事件
boolean sticky() default false;
// 事件订阅优先级,在同一个线程中。数值越大优先级越高。
int priority() default 0;
}
b)定义ThreadMode
public enum ThreadMode {
// 订阅、发布在同一线程。避免了线程切换,也是推荐的默认模式
POSTING,
// 主线程(UI线程)中被调用,切勿耗时操作
MAIN,
// 用于网络访问等耗时操作,事件总线已完成的异步订阅通知线程。并使用线程池有效地重用
ASYNC
}
c)定义订阅方法的描述类
public interface SubscriberInfo {
// 订阅所属类,比如:MainActivity
Class<?> getSubscriberClass();
// 获取订阅所属类中所有订阅事件的方法(此处不使用List是因为注解处理器每次都要list.clear(),麻烦!)
SubscriberMethod[] getSubscriberMethods();
}
public class EventBeans implements SubscriberInfo {
// 订阅者对象Class,如:MainActivity.class
private final Class subscriberClass;
// 订阅方法数组,参考SimpleSubscriberInfo.java 25行
private final SubscriberMethod[] methodInfos;
public EventBeans(Class subscriberClass, SubscriberMethod[] methodInfos) {
this.subscriberClass = subscriberClass;
this.methodInfos = methodInfos;
}
@Override
public Class<?> getSubscriberClass() {
return subscriberClass;
}
@Override
public synchronized SubscriberMethod[] getSubscriberMethods() {
return methodInfos;
}
}
public class SubscriberMethod {
private String methodName; // 订阅方法名
private Method method; // 订阅方法,用于最后的自动执行订阅方法
private ThreadMode threadMode; // 线程模式
private Class<?> eventType; // 事件对象Class,如:UserInfo.class
private int priority; // 事件订阅优先级(实现思路:重排序集合中方法的顺序)
private boolean sticky; // 是否粘性事件(实现思路:发送时存储,注册时判断粘性再激活)
public SubscriberMethod(Class subscriberClass, String methodName,
Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
this.methodName = methodName;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
try {
// 订阅所属类(参考源码:AbstractSubscriberInfo.java - 72行)
method = subscriberClass.getDeclaredMethod(methodName, eventType);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
...
}
d)定义订阅索引接口
public interface SubscriberInfoIndex {
/**
* 生成索引接口,通过订阅者对象(MainActivity.class)获取所有订阅方法
*
* @param subscriberClass 订阅者对象Class,如:MainActivity.class
* @return 事件订阅方法封装类
*/
SubscriberInfo getSubscriberInfo(Class<?> subscriberClass);
}
// 注解处理器的实现
/**
* 编码此类1句话:细心再细心,出了问题debug真的不好调试
*/
// 用来生成 META-INF/services/javax.annotation.processing.Processor 文件
@AutoService(Processor.class)
// 允许/支持的注解类型,让注解处理器处理
@SupportedAnnotationTypes({Constants.SUBSCRIBE_ANNOTATION_TYPES})
// 指定JDK编译版本
@SupportedSourceVersion(SourceVersion.RELEASE_7)
// 注解处理器接收的参数
@SupportedOptions({Constants.PACKAGE_NAME, Constants.CLASS_NAME})
public class SubscribeProcessor extends AbstractProcessor {
// 操作Element工具类 (类、函数、属性都是Element)
private Elements elementUtils;
// type(类信息)工具类,包含用于操作TypeMirror的工具方法
private Types typeUtils;
// Messager用来报告错误,警告和其他提示信息
private Messager messager;
// 文件生成器 类/资源,Filter用来创建新的类文件,class文件以及辅助文件
private Filer filer;
// APT包名
private String packageName;
// APT类名
private String className;
// 临时map存储,用来存放订阅方法信息,生成路由组类文件时遍历
// key:组名"MainActivity", value:MainActivity中订阅方法集合
private final Map<TypeElement, List<ExecutableElement>> methodsByClass = new HashMap<>();
// 该方法主要用于一些初始化的操作,通过该方法的参数ProcessingEnvironment可以获取一些列有用的工具类
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
// 初始化
elementUtils = processingEnvironment.getElementUtils();
typeUtils = processingEnvironment.getTypeUtils();
messager = processingEnvironment.getMessager();
filer = processingEnvironment.getFiler();
// 通过ProcessingEnvironment去获取对应的参数
Map<String, String> options = processingEnvironment.getOptions();
if (!EmptyUtils.isEmpty(options)) {
packageName = options.get(Constants.PACKAGE_NAME);
className = options.get(Constants.CLASS_NAME);
messager.printMessage(Diagnostic.Kind.NOTE,
"packageName >>> " + packageName + " / className >>> " + className);
}
// 必传参数判空(乱码问题:添加java控制台输出中文乱码)
if (EmptyUtils.isEmpty(packageName) || EmptyUtils.isEmpty(className)) {
messager.printMessage(Diagnostic.Kind.ERROR, "注解处理器需要的参数为空,请在对应build.gradle配置参数");
}
}
/**
* 相当于main函数,开始处理注解
* 注解处理器的核心方法,处理具体的注解,生成Java文件
*
* @param set 使用了支持处理注解的节点集合
* @param roundEnvironment 当前或是之前的运行环境,可以通过该对象查找的注解。
* @return true 表示后续处理器不会再处理(已经处理完成)
*/
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
// 一旦有类之上使用@Subscribe注解
if (!EmptyUtils.isEmpty(set)) {
// 获取所有被 @Subscribe 注解的 元素集合
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Subscribe.class);
if (!EmptyUtils.isEmpty(elements)) {
// 解析元素
try {
parseElements(elements);
return true;
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
return false;
}
// 解析所有被 @Subscribe 注解的 类元素集合
private void parseElements(Set<? extends Element> elements) throws IOException {
// 遍历节点
for (Element element : elements) {
// @Subscribe注解只能在方法之上(尽量避免使用instanceof进行判断)
if (element.getKind() != ElementKind.METHOD) {
messager.printMessage(Diagnostic.Kind.ERROR, "仅解析@Subscribe注解在方法上元素");
return;
}
// 强转方法元素
ExecutableElement method = (ExecutableElement) element;
// 检查方法,条件:订阅方法必须是非静态的,公开的,参数只能有一个
if (checkHasNoErrors(method)) {
// 获取封装订阅方法的类(方法上一个节点)
TypeElement classElement = (TypeElement) method.getEnclosingElement();
// 以类名为key,保存订阅方法
List<ExecutableElement> methods = methodsByClass.get(classElement);
if (methods == null) {
methods = new ArrayList<>();
methodsByClass.put(classElement, methods);
}
methods.add(method);
}
messager.printMessage(Diagnostic.Kind.NOTE, "遍历注解方法:" + method.getSimpleName().toString());
}
// 通过Element工具类,获取SubscriberInfoIndex类型
TypeElement subscriberIndexType = elementUtils.getTypeElement(Constants.SUBSCRIBERINFO_INDEX);
// 生成类文件
createFile(subscriberIndexType);
}
private void createFile(TypeElement subscriberIndexType) throws IOException {
// 添加静态块代码:SUBSCRIBER_INDEX = new HashMap();
CodeBlock.Builder codeBlock = CodeBlock.builder();
codeBlock.addStatement("$N = new $T<$T, $T>()",
Constants.FIELD_NAME,
HashMap.class,
Class.class,
SubscriberInfo.class);
// 双层循环,第一层遍历被@Subscribe注解的方法所属类。第二层遍历每个类中所有订阅的方法
for (Map.Entry<TypeElement, List<ExecutableElement>> entry : methodsByClass.entrySet()) {
// 此处不能使用codeBlock,会造成错误嵌套
CodeBlock.Builder contentBlock = CodeBlock.builder();
CodeBlock contentCode = null;
String format;
for (int i = 0; i < entry.getValue().size(); i++) {
// 获取每个方法上的@Subscribe注解中的注解值
Subscribe subscribe = entry.getValue().get(i).getAnnotation(Subscribe.class);
// 获取订阅事件方法所有参数
List<? extends VariableElement> parameters = entry.getValue().get(i).getParameters();
// 获取订阅事件方法名
String methodName = entry.getValue().get(i).getSimpleName().toString();
// 注意:此处还可以做检查工作,比如:参数类型必须是类或接口类型(这里缩减了)
TypeElement parameterElement = (TypeElement) typeUtils.asElement(parameters.get(0).asType());
// 如果是最后一个添加,则无需逗号结尾
if (i == entry.getValue().size() - 1) {
format = "new $T($T.class, $S, $T.class, $T.$L, $L, $L)";
} else {
format = "new $T($T.class, $S, $T.class, $T.$L, $L, $L),\n";
}
// new SubscriberMethod(MainActivity.class, "abc", UserInfo.class, ThreadMode.POSTING, 0, false)
contentCode = contentBlock.add(format,
SubscriberMethod.class,
ClassName.get(entry.getKey()),
methodName,
ClassName.get(parameterElement),
ThreadMode.class,
subscribe.threadMode(),
subscribe.priority(),
subscribe.sticky())
.build();
}
if (contentCode != null) {
// putIndex(new EventBeans(MainActivity.class, new SubscriberMethod[] {)
codeBlock.beginControlFlow("putIndex(new $T($T.class, new $T[]",
EventBeans.class,
ClassName.get(entry.getKey()),
SubscriberMethod.class)
// 嵌套的精华(尝试了很多次,有更好的方式请告诉我)
.add(contentCode)
// ))}
.endControlFlow("))");
} else {
messager.printMessage(Diagnostic.Kind.ERROR, "注解处理器双层循环发生错误!");
}
}
// 全局属性:Map, SubscriberMethod>
TypeName fieldType = ParameterizedTypeName.get(
ClassName.get(Map.class), // Map
ClassName.get(Class.class), // Map
ClassName.get(SubscriberInfo.class) // Map
);
// putIndex方法参数:putIndex(SubscriberInfo info)
ParameterSpec putIndexParameter = ParameterSpec.builder(
ClassName.get(SubscriberInfo.class),
Constants.PUTINDEX_PARAMETER_NAME)
.build();
// putIndex方法配置:private static void putIndex(SubscriberMethod info) {
MethodSpec.Builder putIndexBuidler = MethodSpec
.methodBuilder(Constants.PUTINDEX_METHOD_NAME) // 方法名
.addModifiers(Modifier.PRIVATE, Modifier.STATIC) // private static修饰符
.addParameter(putIndexParameter); // 添加方法参数
// 不填returns默认void返回值
// putIndex方法内容:SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
putIndexBuidler.addStatement("$N.put($N.getSubscriberClass(), $N)",
Constants.FIELD_NAME,
Constants.PUTINDEX_PARAMETER_NAME,
Constants.PUTINDEX_PARAMETER_NAME);
// getSubscriberInfo方法参数:Class subscriberClass
ParameterSpec getSubscriberInfoParameter = ParameterSpec.builder(
ClassName.get(Class.class),
Constants.GETSUBSCRIBERINFO_PARAMETER_NAME)
.build();
// getSubscriberInfo方法配置:public SubscriberMethod getSubscriberInfo(Class> subscriberClass) {
MethodSpec.Builder getSubscriberInfoBuidler = MethodSpec
.methodBuilder(Constants.GETSUBSCRIBERINFO_METHOD_NAME) // 方法名
.addAnnotation(Override.class) // 重写方法注解
.addModifiers(Modifier.PUBLIC) // public修饰符
.addParameter(getSubscriberInfoParameter) // 方法参数
.returns(SubscriberInfo.class); // 方法返回值
// getSubscriberInfo方法内容:return SUBSCRIBER_INDEX.get(subscriberClass);
getSubscriberInfoBuidler.addStatement("return $N.get($N)",
Constants.FIELD_NAME,
Constants.GETSUBSCRIBERINFO_PARAMETER_NAME);
// 构建类
TypeSpec typeSpec = TypeSpec.classBuilder(className)
// 实现SubscriberInfoIndex接口
.addSuperinterface(ClassName.get(subscriberIndexType))
// 该类的修饰符
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
// 添加静态块(很少用的api)
.addStaticBlock(codeBlock.build())
// 全局属性:private static final Map, SubscriberMethod> SUBSCRIBER_INDEX
.addField(fieldType, Constants.FIELD_NAME, Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
// 第一个方法:加入全局Map集合
.addMethod(putIndexBuidler.build())
// 第二个方法:通过订阅者对象(MainActivity.class)获取所有订阅方法
.addMethod(getSubscriberInfoBuidler.build())
.build();
// 生成类文件:EventBusIndex
JavaFile.builder(packageName, // 包名
typeSpec) // 类构建完成
.build() // JavaFile构建完成
.writeTo(filer); // 文件生成器开始生成类文件
}
/**
* 检查方法,条件:订阅方法必须是非静态的,公开的,参数只能有一个
*
* @param element 方法元素
* @return 检查是否通过
*/
private boolean checkHasNoErrors(ExecutableElement element) {
// 不能为static静态方法
if (element.getModifiers().contains(Modifier.STATIC)) {
messager.printMessage(Diagnostic.Kind.ERROR, "订阅事件方法不能是static静态方法", element);
return false;
}
// 必须是public修饰的方法
if (!element.getModifiers().contains(Modifier.PUBLIC)) {
messager.printMessage(Diagnostic.Kind.ERROR, "订阅事件方法必须是public修饰的方法", element);
return false;
}
// 订阅事件方法必须只有一个参数
List<? extends VariableElement> parameters = ((ExecutableElement) element).getParameters();
if (parameters.size() != 1) {
messager.printMessage(Diagnostic.Kind.ERROR, "订阅事件方法有且仅有一个参数", element);
return false;
}
return true;
}
}
public class EventBus {
// volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存
private static volatile EventBus defaultInstance;
// 索引接口
private SubscriberInfoIndex subscriberInfoIndexes;
// 订阅者类型集合,比如:订阅者MainActivity订阅了哪些EventBean,或者解除订阅的缓存。
// key:订阅者MainActivity.class,value:EventBean集合
private Map<Object, List<Class<?>>> typesBySubscriber;
// 方法缓存:key:订阅者MainActivity.class,value:订阅方法集合
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
// EventBean缓存,key:UserInfo.class,value:订阅者(可以是多个Activity)中所有订阅的方法集合
private Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// 粘性事件缓存,key:UserInfo.class,value:UserInfo
private final Map<Class<?>, Object> stickyEvents;
// 发送(子线程) - 订阅(主线程)
private Handler handler;
// 发送(主线程) - 订阅(子线程)
private ExecutorService executorService;
private EventBus() {
// 初始化缓存集合
typesBySubscriber = new HashMap<>();
subscriptionsByEventType = new HashMap<>();
stickyEvents = new HashMap<>();
// Handler高级用法:将handler放在主线程使用
handler = new Handler(Looper.getMainLooper());
// 创建一个子线程(缓存线程池)
executorService = Executors.newCachedThreadPool();
}
// 单例,全局唯一,参考EventBus.java 80行
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
// 添加索引(简化),接口 = 接口实现类,参考EventBusBuilder.java 136行
public void addIndex(SubscriberInfoIndex index) {
subscriberInfoIndexes = index;
}
// 注册 / 订阅事件,参考EventBus.java 138行
public void register(Object subscriber) {
// 获取MainActivity.class
Class<?> subscriberClass = subscriber.getClass();
// 寻找(MainActivity.class)订阅方法集合
List<SubscriberMethod> subscriberMethods = findSubscriberMethods(subscriberClass);
synchronized (this) { // 同步锁,并发少可考虑删除(参考源码)
for (SubscriberMethod subscriberMethod : subscriberMethods) {
// 遍历后,开始订阅
subscribe(subscriber, subscriberMethod);
}
}
}
// 寻找(MainActivity.class)订阅方法集合,参考SubscriberMethodFinder.java 55行
private List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
// 从方法缓存中读取
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
// 找到了缓存,直接返回
if (subscriberMethods != null) {
return subscriberMethods;
}
// 找不到,从APT生成的类文件中寻找
subscriberMethods = findUsingInfo(subscriberClass);
if (subscriberMethods != null) {
// 存入缓存
METHOD_CACHE.put(subscriberClass, subscriberMethods);
}
return subscriberMethods;
}
// 遍历中……并开始订阅,参考EventBus.java 149行
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
// 获取订阅方法参数类型,如:UserInfo.class
Class<?> eventType = subscriberMethod.getEventType();
// 临时对象存储
Subscription subscription = new Subscription(subscriber, subscriberMethod);
// 读取EventBean缓存
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
// 初始化集合
subscriptions = new CopyOnWriteArrayList<>();
// 存入缓存
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(subscription)) {
Log.e("netease >>> ", subscriber.getClass() + "重复注册粘性事件!");
// 执行多次粘性事件,但不添加到集合,避免订阅方法多次执行
sticky(subscriberMethod, eventType, subscription);
return;
}
}
// 订阅方法优先级处理。第一次进来肯定是0,参考EventBus.java 163行
int size = subscriptions.size();
// 这里的i <= size,否则进不了下面条件
for (int i = 0; i <= size; i++) {
// 如果满足任一条件则进入循环(第1次 i = size = 0)
// 第2次,size不为0,新加入的订阅方法匹配集合中所有订阅方法的优先级
if (i == size || subscriberMethod.getPriority() > subscriptions.get(i).subscriberMethod.getPriority()) {
// 如果新加入的订阅方法优先级大于集合中某订阅方法优先级,则插队到它之前一位
if (!subscriptions.contains(subscription)) subscriptions.add(i, subscription);
// 优化:插队成功就跳出(找到了加入集合点)
break;
}
}
// 订阅者类型集合,比如:订阅者MainActivity订阅了哪些EventBean,或者解除订阅的缓存
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
// 存入缓存
typesBySubscriber.put(subscriber, subscribedEvents);
}
// 注意:subscribe()方法在遍历过程中,所以一直在添加
subscribedEvents.add(eventType);
sticky(subscriberMethod, eventType, subscription);
}
// 抽取原因:可执行多次粘性事件,而不会出现闪退,参考EventBus.java 158行
private void sticky(SubscriberMethod subscriberMethod, Class<?> eventType, Subscription subscription) {
// 粘性事件触发:注册事件就激活方法,因为整个源码只有此处遍历了。
// 最佳切入点原因:1,粘性事件的订阅方法加入了缓存。2,注册时只有粘性事件直接激活方法(隔离非粘性事件)
// 新增开关方法弊端:粘性事件未在缓存中,无法触发订阅方法。且有可能多次执行post()方法
if (subscriberMethod.isSticky()) { // 参考EventBus.java 178行
// 源码中做了继承关系的处理,也说明了迭代效率和更改数据结构方便查找,这里就省略了(真实项目极少)
Object stickyEvent = stickyEvents.get(eventType);
// 发送事件 到 订阅者的所有订阅方法,并激活方法
if (stickyEvent != null) postToSubscription(subscription, stickyEvent);
}
}
// 从APT生成的类文件中寻找订阅方法集合,参考SubscriberMethodFinder.java 64行
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
// app在运行时寻找索引,报错了则说明没有初始化索引方法
if (subscriberInfoIndexes == null) {
throw new RuntimeException("未添加索引方法:addIndex()");
}
// 接口持有实现类的引用
SubscriberInfo info = subscriberInfoIndexes.getSubscriberInfo(subscriberClass);
// 数组转List集合,参考EventBus生成的APT类文件
if (info != null) return Arrays.asList(info.getSubscriberMethods());
return null;
}
// 是否已经注册 / 订阅,参考EventBus.java 217行
public synchronized boolean isRegistered(Object subscriber) {
return typesBySubscriber.containsKey(subscriber);
}
// 解除某订阅者关系,参考EventBus.java 239行
public synchronized void unregister(Object subscriber) {
// 从缓存中移除
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
// 移除前清空集合
subscribedTypes.clear();
typesBySubscriber.remove(subscriber);
}
}
// 发送粘性事件,最终还是调用了post方法,参考EventBus.java 301行
public void postSticky(Object event) {
// 同步锁保证并发安全(小项目可忽略此处)
synchronized (stickyEvents) {
// 加入粘性事件缓存集合
stickyEvents.put(event.getClass(), event);
}
// 巨坑!!!源码这么写我也不知道什么意图。恶心的后果:只要参数匹配,粘性/非粘性订阅方法全部执行
// post(event);
}
// 获取指定类型的粘性事件,参考EventBus.java 314行
public <T> T getStickyEvent(Class<T> eventType) {
// 同步锁保证并发安全(小项目可忽略此处)
synchronized (stickyEvents) {
// cast方法做转换类型时安全措施(简化stickyEvents.get(eventType))
return eventType.cast(stickyEvents.get(eventType));
}
}
// 移除指定类型的粘性事件(此处返回值看自己需求,可为boolean),参考EventBus.java 325行
public <T> T removeStickyEvent(Class<T> eventType) {
// 同步锁保证并发安全(小项目可忽略此处)
synchronized (stickyEvents) {
return eventType.cast(stickyEvents.remove(eventType));
}
}
// 移除所有粘性事件,参考EventBus.java 352行
public void removeAllStickyEvents() {
// 同步锁保证并发安全(小项目可忽略此处)
synchronized (stickyEvents) {
// 清理集合
stickyEvents.clear();
}
}
// 发送消息 / 事件
public void post(Object event) {
// 此处两个参数,简化了源码,参考EventBus.java 252 - 265 - 384 - 400行
postSingleEventForEventType(event, event.getClass());
}
// 为EventBean事件类型发布单个事件(遍历),EventBus核心:参数类型必须一致!!!
private void postSingleEventForEventType(Object event, Class<?> eventClass) {
// 从EventBean缓存中,获取所有订阅者和订阅方法
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
// 同步锁,保证并发安全
subscriptions = subscriptionsByEventType.get(eventClass);
}
// 判空,健壮性代码
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
// 遍历,寻找发送方指定的EventBean,匹配的订阅方法的EventBean
postToSubscription(subscription, event);
}
}
}
// 发送事件 到 订阅者的所有订阅方法(遍历中……),参考参考EventBus.java 427行
private void postToSubscription(final Subscription subscription, final Object event) {
// 匹配订阅方的线程模式
switch (subscription.subscriberMethod.getThreadMode()) {
case POSTING: // 订阅、发布在同一线程
invokeSubscriber(subscription, event);
break;
case MAIN:
// 订阅方是主线程,则主 - 主
if (Looper.myLooper() == Looper.getMainLooper()) {
invokeSubscriber(subscription, event);
} else {
// 订阅方是子线程,则子 - 主
handler.post(new Runnable() {
@Override
public void run() {
invokeSubscriber(subscription, event);
}
});
}
break;
case ASYNC:
// 订阅方是主线程,则主 - 子
if (Looper.myLooper() == Looper.getMainLooper()) {
// 主线程 - 子线程,创建一个子线程(缓存线程池)
executorService.execute(new Runnable() {
@Override
public void run() {
invokeSubscriber(subscription, event);
}
});
} else {
// 订阅方是子线程,则子 - 子
invokeSubscriber(subscription, event);
}
break;
default:
throw new IllegalStateException("未知线程模式!" + subscription.subscriberMethod.getThreadMode());
}
}
// 执行订阅方法(被注解方法自动执行)参考EventBus.java 505行
private void invokeSubscriber(Subscription subscription, Object event) {
try {
// 无论3.0之前还是之后。最后一步终究逃不过反射!
subscription.subscriberMethod.getMethod().invoke(subscription.subscriber, event);
} catch (Exception e) {
e.printStackTrace();
}
}
// 清理静态缓存(视项目规模调用)
public static void clearCaches() {
METHOD_CACHE.clear();
}
}
javaPoet生成的类文件格式为:
public final class EventBusIndex implements SubscriberInfoIndex {
private static final Map<Class, SubscriberInfo> SUBSCRIBER_INDEX;
static {
SUBSCRIBER_INDEX = new HashMap<Class, SubscriberInfo>();
putIndex(new EventBeans(MainActivity.class, new SubscriberMethod[] {
new SubscriberMethod(MainActivity.class, "handleMessageEvent", MessageEvent.class, ThreadMode.MAIN, 0, false)} ));
}
private static void putIndex(SubscriberInfo info) {
SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
}
@Override
public SubscriberInfo getSubscriberInfo(Class subscriberClass) {
return SUBSCRIBER_INDEX.get(subscriberClass);
}
}
源码传送门