您的位置:首页 > 移动开发 > Android开发

Android APT开发教程 六 使用注解替代setOnClickListener还有注释给String赋值

2018-01-24 16:22 711 查看
github项目代码地址
https://github.com/979451341/TestAPT

1.注释代替setOnClickListener

这个注解能够通过绑定控件id和函数,使点击这个控件的时候触发这个函数

如下图

@OnClick(R.id.tv1)
public void click(){
c++;
tv1.setText(c+"");
}
首先是元注解,ElementType指定为函数,并设置一个int类型的变量用来存储id

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {
int value() default  0;
}
然后我们想一下生成什么代码,既然是要用注解代替setOnClick,那我们就生成setOnClick代码

因为之前做了注解代替int赋值和findViewById,所以我们只用在原来的代码改动就好了

for (Element item : members) {
TestInt diView = item.getAnnotation(TestInt.class);
OnClick onClick = item.getAnnotation(OnClick.class);
if (diView == null && onClick == null){
continue;
}

if(diView != null){
if(item.asType().getKind() == INT)
bindViewMethodSpecBuilder.addStatement(String.format("activity.%s = %s",item.getSimpleName(),diView.value()));
if(item.asType().getKind() == DECLARED)
bindViewMethodSpecBuilder.addStatement(String.format("activity.%s = (%s)activity.findViewById(%s)",item.getSimpleName(),item.asType().toString(),diView.value()));

}
if(onClick != null){

String name = item.getSimpleName().toString();
bindViewMethodSpecBuilder.addStatement(String.format("activity.findViewById(%s).setOnClickListener(new android.view.View.OnClickListener() {\n" +
"            @Override\n" +
"            public void onClick(android.view.View v) {\n" +"activity.%s();"+
"                \n" +
"            }\n" +
"        });",onClick.value(),name));
}

}


2.用注解给String赋值

这个应该不写的,因为觉得很low,但是我搞了半天才知道咋弄,不说了直接上关键代码

元注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestString {
String value() default "";
}
使用

    @TestString("aaaa")

    String data;

注解处理器代码生成

bindViewMethodSpecBuilder.addStatement(String.format("activity.%s = \"%s\"",item.getSimpleName(),testString.value()));

说了就是在“”里面再用“就必须要加个\,否则系统判错,这个注意一下就好,像其他的基础类型用注解赋值都是一个样,换个元注解就好了

以下是注解处理器完整代码:

@AutoService(Processor.class)
public class TestProcessor extends AbstractProcessor {
private Elements elementUtils;
@Override
public Set<String> getSupportedAnnotationTypes() {
// 规定需要处理的注解
return Collections.singleton(TestActivity.class.getCanonicalName());
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(TestActivity.class);
for (Element element : elements) {
// 判断是否Class
TypeElement typeElement = (TypeElement) element;
List<? extends Element> members = elementUtils.getAllMembers(typeElement);
TestActivity activity = typeElement.getAnnotation(TestActivity.class);
MethodSpec.Builder bindViewMethodSpecBuilder = MethodSpec.methodBuilder("setDefualt")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(TypeName.VOID)
.addParameter(ClassName.get(typeElement.asType()), "activity",Modifier.FINAL);

if(activity == null){
continue;
}
bindViewMethodSpecBuilder.addStatement(String.format("activity.setContentView(%s)",activity.value()));
for (Element item : members) {
TestInt diView = item.getAnnotation(TestInt.class);
OnClick onClick = item.getAnnotation(OnClick.class);
TestString testString = item.getAnnotation(TestString.class);
if (diView == null && onClick == null && testString == null){
continue;
}

if(diView != null){
if(item.asType().getKind() == INT)
bindViewMethodSpecBuilder.addStatement(String.format("activity.%s = %s",item.getSimpleName(),diView.value()));
if(item.asType().getKind() == DECLARED)
bindViewMethodSpecBuilder.addStatement(String.format("activity.%s = (%s)activity.findViewById(%s)",item.getSimpleName(),item.asType().toString(),diView.value()));

}
if(onClick != null){

String name = item.getSimpleName().toString();
bindViewMethodSpecBuilder.addStatement(String.format("activity.findViewById(%s).setOnClickListener(new android.view.View.OnClickListener() {\n" +
"            @Override\n" +
"            public void onClick(android.view.View v) {\n" +"activity.%s();"+
"                \n" +
"            }\n" +
"        });",onClick.value(),name));
}

if(testString != null){
bindViewMethodSpecBuilder.addStatement(String.format("activity.%s = \"%s\"",item.getSimpleName(),testString.value()));
}

}
TypeSpec typeSpec = TypeSpec.classBuilder("Test" + element.getSimpleName())
.superclass(TypeName.get(typeElement.asType()))
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(bindViewMethodSpecBuilder.build())
.build();
JavaFile javaFile = JavaFile.builder(getPackageName(typeElement), typeSpec).build();
try {
javaFile.writeTo(processingEnv.getFiler());
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
private String getPackageName(TypeElement type) {
return elementUtils.getPackageOf(type).getQualifiedName().toString();
}
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
elementUtils = processingEnv.getElementUtils();
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.RELEASE_7;
}
}
这样就好了,大部分关于Butterknife的常用注解,我们都实现了,这个系列还会写下去,应该继续模仿一些很有名的框架使用的注解做模仿。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐