2019-12-01 17:42:27
该系列介绍自定义注解,完成如下功能。
- @BindView 代替 findViewById
- @ClickResponder 代替 setOnClickListener
- @LongClickResponder 代替 setOnLongClickListener
- @IntentValue 代替 getIntent().getXXX
- @UriValue 代替 getQueryParameter
- @BroadcastResponder 代替 registerReceiver
- @RouterModule、@RouterPath 来进行反依赖传递调用
该系列源码在https://github.com/huangyuanlove/AndroidAnnotation
使用编译时注解,生成辅助类来完成这些操作,尽量少的使用的反射功能。
本章先介绍 javapoet 和一丢丢反射相关的东西
javapoet
用来辅助生成java代码的库,可以看这里,有特别详细的示例。大致过了一遍,如下所示
public class TestJavaPoet {
public static void main(String[] args) {
TypeSpec clazz = clazz(builtinTypeField(), // int
arrayTypeField(), // int[]
refTypeField(), // File
typeField(), // T
parameterizedTypeField(), // List<String>
wildcardTypeField(), // List<? extends String>
constructor(), // 构造函数
method(code())); // 普通方法
JavaFile javaFile = JavaFile.builder("com.huangyuanlove.view_inject_compiler.test", clazz).build();
System.out.println(javaFile.toString());
}
/**
* `public abstract class Clazz<T> extends String implements Serializable, Comparable<String>, Comparable<? extends String> {
* ...
*/
private static TypeSpec clazz(FieldSpec builtinTypeField, FieldSpec arrayTypeField, FieldSpec refTypeField,
FieldSpec typeField, FieldSpec parameterizedTypeField, FieldSpec wildcardTypeField,
MethodSpec constructor, MethodSpec methodSpec) {
return TypeSpec.classBuilder("Clazz")
// 限定符
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
// 泛型
.addTypeVariable(TypeVariableName.get("T"))
// 继承与接口
.superclass(String.class)
.addSuperinterface(Serializable.class)
.addSuperinterface(ParameterizedTypeName.get(Comparable.class, String.class))
.addSuperinterface(ParameterizedTypeName.get(ClassName.get(Map.class),
TypeVariableName.get("T"),
WildcardTypeName.subtypeOf(String.class)))
// 初始化块
.addStaticBlock(CodeBlock.builder().build())
.addInitializerBlock(CodeBlock.builder().build())
// 属性
.addField(builtinTypeField)
.addField(arrayTypeField)
.addField(refTypeField)
.addField(typeField)
.addField(parameterizedTypeField)
.addField(wildcardTypeField)
// 方法 (构造函数也在此定义)
.addMethod(constructor)
.addMethod(methodSpec)
// 内部类
.addType(TypeSpec.classBuilder("InnerClass").build())
.build();
}
/**
* 内置类型
*/
private static FieldSpec builtinTypeField() {
// private int mInt;
return FieldSpec.builder(int.class, "mInt", Modifier.PRIVATE).build();
}
/**
* 数组类型
*/
private static FieldSpec arrayTypeField() {
// private int[] mArr;
return FieldSpec.builder(int[].class, "mArr", Modifier.PRIVATE).build();
}
/**
* 需要导入 import 的类型
*/
private static FieldSpec refTypeField() {
// private File mRef;
return FieldSpec.builder(File.class, "mRef", Modifier.PRIVATE).build();
}
/**
* 泛型
*/
private static FieldSpec typeField() {
// private File mT;
return FieldSpec.builder(TypeVariableName.get("T"), "mT", Modifier.PRIVATE).build();
}
/**
* 参数化类型
*/
private static FieldSpec parameterizedTypeField() {
// private List<String> mParameterizedField;
return FieldSpec.builder(ParameterizedTypeName.get(List.class, String.class),
"mParameterizedField",
Modifier.PRIVATE)
.build();
}
/**
* 通配符参数化类型
*/
private static FieldSpec wildcardTypeField() {
// private List<? extends String> mWildcardField;
return FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(List.class),
WildcardTypeName.subtypeOf(String.class)),
"mWildcardField",
Modifier.PRIVATE)
.build();
}
/**
* 构造函数
*/
private static MethodSpec constructor() {
return MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.build();
}
/**
* `@Override
* public <T> Integer method(String string, T t, Map<Integer, ? extends T> map) throws IOException, RuntimeException {
* ...
* }`
*
*/
private static MethodSpec method(CodeBlock codeBlock) {
return MethodSpec.methodBuilder("method")
.addAnnotation(Override.class)
.addTypeVariable(TypeVariableName.get("T"))
.addModifiers(Modifier.PUBLIC)
.returns(int.class)
.addParameter(String.class, "string")
.addParameter(TypeVariableName.get("T"), "t")
.addParameter(ParameterizedTypeName.get(ClassName.get(Map.class),
ClassName.get(Integer.class),
WildcardTypeName.subtypeOf(TypeVariableName.get("T"))),
"map")
.addException(IOException.class)
.addException(RuntimeException.class)
.addCode(codeBlock)
.build();
}
/**
* ‘method’ 方法中的具体语句
*/
private static CodeBlock code() {
return CodeBlock.builder()
.addStatement("int foo = 1")
.addStatement("$T bar = $S", String.class, "a string")
// Object obj = new HashMap<Integer, ? extends T>(5);
.addStatement("$T obj = new $T(5)",
Object.class, ParameterizedTypeName.get(ClassName.get(HashMap.class),
ClassName.get(Integer.class),
WildcardTypeName.subtypeOf(TypeVariableName.get("T"))))
// method(new Runnable(String param) {
// @Override
// void run() {
// }
// });
.addStatement("baz($L)", TypeSpec.anonymousClassBuilder("$T param", String.class)
.superclass(Runnable.class)
.addMethod(MethodSpec.methodBuilder("run")
.addAnnotation(Override.class)
.returns(TypeName.VOID)
.build())
.build())
// for
.beginControlFlow("for (int i = 0; i < 5; i++)")
.endControlFlow()
// while
.beginControlFlow("while (false)")
.endControlFlow()
// do... while
.beginControlFlow("do")
.endControlFlow("while (false)")
// if... else if... else...
.beginControlFlow("if (false)")
.nextControlFlow("else if (false)")
.nextControlFlow("else")
.endControlFlow()
// try... catch... finally
.beginControlFlow("try")
.nextControlFlow("catch ($T e)", Exception.class)
.addStatement("e.printStackTrace()")
.nextControlFlow("finally")
.endControlFlow()
.addStatement("return 0")
.build();
}
这样就省去了我们自己手动评价代码块的麻烦,提高效率,并且也比较容易查错。
反射
这玩意说起来可就长了,这里只做示例
一个Person类
package com.huangyuanlove;
public class Person {
private int age;
public String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress(){
return "getAddress without param";
}
private String getAddress(String zipCode){
return "getAddress with param:" + zipCode;
}
private Person() {
}
}
玩一下反射
package com.huangyuanlove;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) {
try {
//如果没有对应类的依赖的话(不能直接import),可以用Class.forName
//Class personClass = Class.forName("com.huangyuanlove.Person");
Class<Person> personClass = Person.class;
//调用私有无参构造方法创建对象
Constructor<Person> personConstructor = personClass.getDeclaredConstructor();
personConstructor.setAccessible(true);
Person person = personConstructor.newInstance();
//反射获取公共方法并调用
Method getAddressWithoutParamMethod = personClass.getMethod("getAddress");
System.out.println( getAddressWithoutParamMethod.invoke(person));
//反射获取私有方法并调用
Method getAddressMethod = personClass.getDeclaredMethod("getAddress", String.class);
getAddressMethod.setAccessible(true);
System.out.println(getAddressMethod.invoke(person, "zipCode"));
//反射获取私有字段并赋值
Field ageField = personClass.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(person,11);
System.out.println(person.getAge());
//反射获取私有静态方法并调用
Method sayHiMethod = personClass.getDeclaredMethod("saySomething",String.class);
sayHiMethod.setAccessible(true);
sayHiMethod.invoke(null,"reflect");
} catch (Exception e) {
e.printStackTrace();
}
}
}
以上