之前一直在用EventBus来做应用内的消息发送,但由于现在项目的开发环境不允许使用外网,因此很多第三方库都不能使用,因此自己学习并撸了一套低配的EventBus在此写下来记录一下。
话不多说直接上代码
EventBus主类,主要用于注册方法、发送数据。
/**
* @author wilson
* @since 2019年03月17日22:58:24
*/
public class EventBus {
private final String TAG = getClass().getName();
private static volatile EventBus instance;
private HashMap
在EventBus这个类的一些变量
//用于存放注册的方法
private HashMap> methodCache;
//发送数据到主线程
private Handler handler;
//发送数据到子线程
private ExecutorService cacheExecutorService;
regist方法,该方法用于注册需要监听的类(Activity,Fragment,Object等等)
/**
* 注册需要监听的class
*
* @param object
*/
public void regist(Object object) {
synchronized (EventBus.class) {
List list = methodCache.get(object);
if (list == null) {
list = findSubscribleMethods(object);
methodCache.put(object, list);
}
}
}
findSubscribleMethods方法,该方法主要用于将我们在类里面写的自定义方法
/**
* 将class内带有Subscribe注解的方法及参数添加到缓存集合中
*
* @param object
* @return
*/
private List findSubscribleMethods(Object object) {
List list = new ArrayList<>();
Class> claz = object.getClass();
//获取当前类的所有方法
Method[] declaredMethods = claz.getDeclaredMethods();
while (claz != null) {
//获取当前类的名字,如果是系统方法,就不在继续找注册的方法,因为我们不能把我们自定义的注解写到系统API里
String name = claz.getName();
if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
break;
}
for (Method method : declaredMethods) {
//获取我们写的Subscribe注解
Subscribe annotation = method.getAnnotation(Subscribe.class);
if (annotation != null) {
Class>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1) {
Log.e(TAG, "eventbus 只能处理一个参数");
}
ThreadModel threadModel = annotation.threadMode();
SubscribleMethod subscribleMethod = new SubscribleMethod(method, threadModel, parameterTypes[0]);
//把注解方法对象添加到list中
list.add(subscribleMethod);
}
}
claz = claz.getSuperclass();
}
return list;
}
post 方法,方法数据到订阅的方法,其中threadMode定义了线程的切换
/**
* 发送数据
*
* @param param
*/
public void post(final Object param) {
Set set = methodCache.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
final Object obj = iterator.next();
List list = methodCache.get(obj);
for (final SubscribleMethod method : list) {
if (method.getParam().isAssignableFrom(param.getClass())) {
switch (method.getmThreadModel()) {
case Main:
if (Looper.myLooper() == Looper.getMainLooper()) {
invoke(method, obj, param);
} else {
handler.post(new Runnable() {
@Override
public void run() {
invoke(method, obj, param);
}
});
}
break;
case Background:
//主到子
cacheExecutorService.execute(new Runnable() {
@Override
public void run() {
invoke(method, obj, param);
}
});
break;
}
}
}
}
}
上面方法中的invoke方法,reflect方式调用方法
/**
* 调用注册进来的带有Subscribe注解的方法
*
* @param subscribleMethod 注解方法对象
* @param obj claz
* @param param 参数
*/
private void invoke(SubscribleMethod subscribleMethod, Object obj, Object param) {
Method method1 = subscribleMethod.getmMethod();
try {
method1.invoke(obj, param);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
ThreadModel就是一个简单的枚举类,用于切换子主线程
public enum ThreadModel {
Main, Background
}
自定义注解Subscribe类,该注解作用于方法上,在需要订阅的方法上直接添加该注解即可与原版EventBus使用方式一样
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
ThreadModel threadMode() default ThreadModel.Main;
}
SubscribleMethod 就是一个普通的java bean
public class SubscribleMethod {
private Method mMethod;
private ThreadModel mThreadModel;
private Class> param;
public Method getmMethod() {
return mMethod;
}
public void setmMethod(Method mMethod) {
this.mMethod = mMethod;
}
public ThreadModel getmThreadModel() {
return mThreadModel;
}
public void setmThreadModel(ThreadModel mThreadModel) {
this.mThreadModel = mThreadModel;
}
public Class> getParam() {
return param;
}
public void setParam(Class> param) {
this.param = param;
}
public SubscribleMethod(Method mMethod, ThreadModel mThreadModel, Class> param) {
this.mMethod = mMethod;
this.mThreadModel = mThreadModel;
this.param = param;
}
}
最后就是具体使用了,具体使用与原版的一模一样,只不过这个版本的Eventbus工具,没有像官方的支持粘性事件等等,主要还是为了满足现有项目的一些小小需求而做的。
My github: