背景:
Android组件之间通讯的方式有很多,广播 、intent 、handler、接口等这些都可以实现。网上开源框架EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。通过EventBus源码自己实现线程之间消息传递。
1.介绍EventButs的使用方法:
一:注册EventButs事件:
EventBus.getDefault().register(this);
二:监听EventButs事件:
@Subscribe(threadMode = ThreadMode.MAIN)
public void getEvent(EventBean bean){
Log.e("====>", "thread = " + Thread.currentThread().getName());
Log.e("======> ",bean.toString());
}
三:发送EventButs事件:
EventBus.getDefault().post(new EventBean("1111","22222"));
通过上面的代码就可以实现事件消息在组件之间的传递,下面我将不改变开源框架的代码格式,自己去实现EventButs:
第一步:定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,jvm在加载时可以通过反射的方式获取该注解的内容
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.MAIN;
}
上面添加注解的枚举类:定义的两种类型一种指定主线程另一种为子线程
ublic enum ThreadMode {
MAIN,
BACKGROUND
}
第二步:注册事件
public void register(Object obj){
// 先去数据源中获取subcribleMethods,如果不存在,则去寻找方法并添加
List<SubscribleMethod> list = cacheMap.get(obj);
if(list == null){
list = findSubscribleMethods(obj);
cacheMap.put(obj,list);
}
}
上面的代码主要为从缓存中获取是否添加过监听,避免重复添加。
重点:
findSubscribleMethods 中主要将当前类以及父类中所有添加的注解一一遍历出来,获取注解类的回调方法、数据返回的线程模式、回调方法中的参数类 添加到map缓存 。具体代码如下:
public List<SubscribleMethod> findSubscribleMethods(Object obj){
List<SubscribleMethod> list = new ArrayList<>();
Class<?> clazz = obj.getClass();
// 循环去查找父类是否存在subscrible注解方法
while (clazz != null){
// 判断当前是否是系统类,如果是,就退出循环
String name = clazz.getName();
if(name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")){
break;
}
// 得到所有的方法,这个clazz在本项目中,暂时指代的是MainActivity
Method[] methods = clazz.getMethods();
for(Method method : methods){
// 通过注解找到我们需要注册的方法
Subscribe subscribe = method.getAnnotation(Subscribe.class);
if(subscribe == null){
continue;
}
// 获取方法中的参数,并判断
Class<?>[] types = method.getParameterTypes();
if(types.length != 1){
throw new RuntimeException("EventBus只能接受一个参数");
}
// 获取线程模式
ThreadMode threadMode = subscribe.threadMode();
SubscribleMethod subscribleMethod = new SubscribleMethod(method,threadMode,types[0]);
list.add(subscribleMethod);
}
clazz = clazz.getSuperclass();
}
return list;
}
第三步:发送事件
发生事件为根据当前的发送的对象获取缓存中的注解类,根据当前的线程调度通过反射去执行注解类方法,实现数据的传递。
public void post(final Object type){
Set<Object> set = cacheMap.keySet();
Iterator<Object> iterator = set.iterator();
while (iterator.hasNext()){
final Object obj = iterator.next();
List<SubscribleMethod> list = cacheMap.get(obj);
for(final SubscribleMethod subscribleMethod : list){
// 简单的理解:两个列对比一下,看看是否一致 (不严谨的说法)
// a(subscribleMethod.getType())对象所对应的类信息,是b(type.getClass())对象所对应的类信息的父类或者父接口
if(subscribleMethod.getType().isAssignableFrom(type.getClass())){
switch (subscribleMethod.getThreadMode()){
// 不管你在post是在主线程 还是在子线程,我都在主线程接受
case MAIN:
// 主 - 主
if(Looper.myLooper() == Looper.getMainLooper()){
invoke(subscribleMethod,obj,type);
}else{
// 子 - 主
mHandler.post(new Runnable() {
@Override
public void run() {
invoke(subscribleMethod,obj,type);
}
});
}
break;
case BACKGROUND:
// 主 - 子
if(Looper.myLooper() == Looper.getMainLooper()){
mExecutorService.execute(new Runnable() {
@Override
public void run() {
invoke(subscribleMethod,obj,type);
}
});
}else{
// 子 - 子
invoke(subscribleMethod,obj,type);
}
break;
}
}
}
}
}
private void invoke(SubscribleMethod subscribleMethod, Object obj, Object type) {
Method method = subscribleMethod.getMethod();
try {
method.invoke(obj,type);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
image.png
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BACKGROUND:
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case ASYNC:
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
网友评论