相关教程
ViewBinder简陋实现
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewBinder {
int value() default -1;
}
@RetentionRetention注解表示需要在什么级别保存该注释信息,用于描述注解的生命周期,它有一个RetentionPolicy类型的value,是一个枚举类型,它有以下的几个值:
1.用@Retention(RetentionPolicy.SOURCE)修饰的注解,指定注解只保留在源文件当中,编译成类文件后就把注解去掉;
2.用@Retention(RetentionPolicy.CLASS)修饰的注解,指定注解只保留在源文件和编译后的class 文件中,当jvm加载类时就把注解去掉;
3.用@Retention(RetentionPolicy.RUNTIME )修饰的注解,指定注解可以保留在jvm中,这样就可以使用反射获取信息了。
这里用的是RUNTIME,这样在运行的时候通过反射获取并做对应的逻辑处理。
1.用@Retention(RetentionPolicy.SOURCE)修饰的注解,指定注解只保留在源文件当中,编译成类文件后就把注解去掉;
2.用@Retention(RetentionPolicy.CLASS)修饰的注解,指定注解只保留在源文件和编译后的class 文件中,当jvm加载类时就把注解去掉;
3.用@Retention(RetentionPolicy.RUNTIME )修饰的注解,指定注解可以保留在jvm中,这样就可以使用反射获取信息了。
这里用的是RUNTIME,这样在运行的时候通过反射获取并做对应的逻辑处理。
import android.app.Activity;
import android.view.View;
import java.lang.reflect.Field;
public class ViewBinderParser implements Parsable {
private ViewBinderParser() {}
public static void inject(Object object) {
ViewBinderParser parser = new ViewBinderParser();
try {
parser.parser(object);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void parser(Object object) throws Exception {
View view = null;
final Class<?> clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(ViewBinder.class)) {
ViewBinder inject = field.getAnnotation(ViewBinder.class);
int id = inject.value();
if (id < 0) {
throw new Exception("id must not be null");
}
if (id > 0) {
field.setAccessible(true);
if (object instanceof View) {
view = ((View) object).findViewById(id);
} else if (object instanceof Activity) {
view = ((Activity) object).findViewById(id);
}
field.set(object, view);
}
}
}
}
}
interface Parsable {
void parser(final Object object) throws Exception;
}
使用:
@ViewBinder(R.id.mainTv)
TextView tv;
@ViewBinder(R.id.mainWv)
WebView wv;
ButterKnife的实现
前面实现的是在运行时绑定会影响性能,而ButterKnife中ButterKnifeProcessor.java 的 process 方法如上,编译时,在此方法中过滤 InjectView 这个 Annotation 到 targetClassMap 后,会根据 targetClassMap 中元素生成不同的 class 文件到最终的 APK 中,然后在运行时调用 ButterKnife.bind(x) 函数时会到之前编译时生成的类中去找。这样性能损失就会非常小。