Android- 创建一个简单的事件订阅组件(一)
介绍
本文将基于反射与注解来介绍如何创建一个简单的事件订阅组件.
概述
本文中使用到的注解
1. @Documented —— 指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明 的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。
2. @Target——指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为TYPE,METHOD,CONSTRUCTOR,FIELD等。如果 Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。
3.@Retention——指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。
1.既然使用到了注解,那么我们首先创建一个注解类
@Documented
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target({ElementType.METHOD}) //只使用在方法上
public @interface Register {
}
2.创建注册与解绑
//注册
EventHelper.getInstance().register(this);
//解绑
EventHelper.getInstance().unregister(this);
3.既然是事件订阅。那么我们需支持所有的类。包括但不限于(Activity,Fragment,View,自定义类);那么发送的类型为object类型
EventHelper.getInstance().postEvent(new User("你大爷"));
至此 外层调用方法结束。接下来我们实现内部逻辑.
首先开始注册方法register() ,对注册的类必须进行校验来保证事件订阅的成功。如果成功情况下存进map。
public void register(Object object) {
Class<?> aClass = object.getClass();
//加入前先校验是否有注解了方法
checkHasMethod(aClass);
classHashMap.put(object.hashCode(), object);
}
该方法对传进来的类进行了方法校验及注解校验.这里的获取方法不推荐getDeclaredMethods(),而是推荐使用公共参数来减少遍历层。
/**
* 校验类方法名
*
* @param aClass
*/
private void checkHasMethod(Class<?> aClass) {
Method[] methods = aClass.getMethods();
boolean has_on_event = false;
int j = 0;
for (int i = 0; i < methods.length; i++) {
String name = methods[i].getName();
Log.i(TAG, "checkHasMethod name:" + name);
if (name.equals("onEvent")) {
has_on_event = true;
j = i;
break;
} else {
has_on_event = false;
}
}
if (!has_on_event) {
throw new EventException("注册的类里没有onEvent方法或非公共参数");
}
Register annotation = methods[j].getAnnotation(Register.class); //检测注解
if (annotation == null) {
throw new EventException("注册的onEvent方法未使用Register注解");
}
}
对于解绑操作。我们只要将map里对应的实例移除即可;
post方法
public synchronized void postEvent(Object event) {
//向所有注册的类发送事件
for (Map.Entry<Integer, Object> entry : classHashMap.entrySet()) {
Object value = entry.getValue();
Class aClass = value.getClass();
try {
//
Method[] methods = aClass.getMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if (method.getName().equals("onEvent")) {
method.invoke(value, event);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void unregister(Object object) {
classHashMap.remove(object.hashCode());
}
至此整个事件订阅完成,我们来简单的测试一下 MainActivity 创建onEvent方法并使用@Register注解
二级页面也创建一个
发送事件
2个页面成功接收到了参数。
以上只是对注解进行了简单的使用。还能有更复杂的用法及更简便的配置
如
@Documented
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target({ElementType.METHOD}) //只使用在方法上
public @interface Register {
String value();
}
使用注解来配置所接收的事件;简化流程;
当然以上的简易Demo 对于 多方法还是不支持的。
如何支持,及使用注解来简化流程,下一章节分晓。(待更。)