其实在我们开发当中需要应用组件与后台线程间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过Handler或者是广播通知UI,而两个Fragment之家可以通过Listener进行通信等等。当我们的项目越来越复杂,使用Intent、Handler、Broadcast进行模块间通信、模块与后台线程进行通信时,代码量大,而且高度耦合;最近公司正在做了一款项目是要求模块化来做,前期考虑是想用阿里的ARouter实现模块间的跳转和传值,因为我们公司App设计是一个Activity其别的页面都是显示用Fragment去展示的,考虑到返回容器的处理觉得ARouter不适合,就选择了EventBus来实现模块间的跳转和传值,下面带大家了解下EventBus。
EventBus是Android和Java的发布/订阅事件总线;
事件总线是对发布–订阅模式的一种实现。他是一种集中式事件处理机制,允许不同的组件之间彼此通信而不需要相互依赖,达到解耦的目的。
一:Event 事件;
二:Subscriber 事件订阅者;
三:Publisher 事件发布者;
POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程;
MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作;
BACKGROUND 表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程;
ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作;
一: 代码简单,快;
二:jar包小;
三:Activity、Fragment以及线程间通信优秀;
四:稳定;
MyEventBus.getDefault().register(this);
@Subscrible(threadMode = ThreadMode.MAIN)//线程为主线程
public void getMessage(EventBean eventBean){
Toast.makeText(MainActivity.this,eventBean.toString(),Toast.LENGTH_SHORT).show();
Log.e("main", eventBean.toString());
}
@Target(ElementType.METHOD)//注解到方法上面
@Retention(RetentionPolicy.RUNTIME)//定义运行时
public @interface Subscrible {
//
ThreadMode threadMode() default ThreadMode.MAIN;
}
public enum ThreadMode {
MAIN,
BACHGROUND
}
public class EventBean {
private String name;
private String msg;
public EventBean(final String name, final String msg) {
this.name = name;
this.msg = msg;
}
@Override
public String toString() {
return "EventBean{" +
"name='" + name + '\'' +
", msg='" + msg + '\'' +
'}';
}
}
public class MyEventBus {
//定义一个容器来存放方法
private Map<Object, List<SubscribleMethod>> cacheMap;
private Handler mHandler;
private static volatile MyEventBus instance;
private MyEventBus() {
cacheMap = new HashMap<>();
mHandler = new Handler();
}
public static MyEventBus getDefault() {
if (instance == null) {
synchronized (MyEventBus.class) {
if (instance == null) {
instance = new MyEventBus();
}
}
}
return instance;
}
// 在这个方法中去判断所有当前类的所有方法
public void register(Object obj) {
// 首先在map集合取当前类的集合
List<SubscribleMethod> list = cacheMap.get(obj);
if (list == null) {
// 定义方法取
list = findSubscribleMethods(obj);
// 存到容器
cacheMap.put(obj, list);
}
}
private List<SubscribleMethod> findSubscribleMethods(final Object obj) {
// 定义一个集合
List<SubscribleMethod> list = new ArrayList<>();
//
Class<?> aClass = obj.getClass();
// 可以得到当前类的所有方法 此方法获取不带父类的方法
Method[] methods = aClass.getDeclaredMethods();
// // 若是取父类的方法 用下面方法
// Method[] methods1 = aClass.getMethods();
while (aClass != null) {//此循环是向父类一层层往上找
// 找父类的时候是要先判断下是否是系统级别的父类
String name = aClass.getName();
// 判断是系统级别的名字就停止
if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
break;
}
// 遍历所有方法
for (Method method : methods) {
// 找到带Subscrible注解的方法,
Subscrible subscrible = method.getAnnotation(Subscrible.class);
if (subscrible == null) {
continue;
}
// 获取subscrible的参数类型
Class<?>[] types = method.getParameterTypes();
// 不为空的时候就判断下带有subscrible注解的方法参数类型
if (types.length == 1) {
}
ThreadMode threadMode = subscrible.threadMode();
SubscribleMethod subscribleMethod = new SubscribleMethod(method, threadMode, types[0]);
list.add(subscribleMethod);
}
// 等于父类的类
aClass =aClass.getSuperclass();
}
return list;
}
// 发送evengtbus的方法
public void post(final Object type) {
// 直接循环map里面的方法,找到对应的然后调用
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) {//遍历
// 判断方法的参数是否相等
if (subscribleMethod.getType().isAssignableFrom(type.getClass())){
// 判断下线程
switch (subscribleMethod.getThreadMode()){
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 BACHGROUND: //后续添加
break;
}
}
}
}
}
// 是一个回调的方法
private void invoke(final SubscribleMethod subscribleMethod, final Object obj, final Object type) {
Method method = subscribleMethod.getMethod();
try {
method.invoke(obj,type);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
上面代码主要是实现一个简单的EventBus实现数据传递,因为源码里面还有好多方法后续会陆续添加,也希望更多的小伙伴多多提下意见,共同进步下面给大家提供本人github地址本人已经上传望大家共同改进。