Android APT开发教程 五 使用注释完成findViewById和setConten
2018-01-30 19:43
501 查看
github项目代码地址
https://github.com/979451341/TestAPT
之前我们做了一个能够给int赋值的apt,这个时候我想到好像控件类似TextView的id值也是int类型,所以我也可以给控件id赋值
不过有一个问题就是如何去分辨哪个是int类型,哪个是控件的id
但是我们可以去试一下获取这两种元素的信息有何不同
比如我这样一弄,就可以打印出类似Element类似分类的属性
@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");
结果如下
public final class TestMainActivity extends MainActivity {
public static void setDefualt(MainActivity activity) {
}
}
可以看到item.asType().getKind()能够分辨控件id和int类型的区别,
我把加代码的那段换成如下,就是判断如果类型为INT就正常int赋值,如果类型为DECLARED就findViewById
后来通过实验,代码运行正常,
@TestActivity
public class MainActivity extends Activity {
}
但是我还记得R.layout.activity_main也是int类型,我们应该能够使用注解来设置布局,这注解用在哪呢,我就用在TestActivity这个注解吧
那我就要改变TestActivity的代码,加个int的变量
@Target(ElementType.TYPE)[url=mailto:br/>@Retention(RetentionPolicy.CLASS)
@Retention(RetentionPolicy.CLASS)
int value() default 0;
}
然后在注解处理器里添加一行接收TestActivity的value值并给Activity设置布局的代码
使用如下:
@TestActivity(R.layout.activity_main)
public class MainActivity extends Activity {
}
完整的注释处理器代码如下
@AutoService(Processor.class)
public class TestProcessor extends AbstractProcessor {
private Elements elementUtils;[url=mailto:br/>@Override
@Override
// 规定需要处理的注解
return Collections.singleton(TestActivity.class.getCanonicalName());[url=mailto:br/>}
@Override
}
@Override
https://github.com/979451341/TestAPT
之前我们做了一个能够给int赋值的apt,这个时候我想到好像控件类似TextView的id值也是int类型,所以我也可以给控件id赋值
不过有一个问题就是如何去分辨哪个是int类型,哪个是控件的id
但是我们可以去试一下获取这两种元素的信息有何不同
比如我这样一弄,就可以打印出类似Element类似分类的属性
@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");
for (Element item : members) { TestInt diView = item.getAnnotation(TestInt.class); if (diView == null){ continue; } bindViewMethodSpecBuilder.addStatement(String.format("%s %s",item.getKind(),item.asType().getKind())); } 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; }
结果如下
public final class TestMainActivity extends MainActivity {
public static void setDefualt(MainActivity activity) {
FIELD INT; FIELD INT; FIELD INT; FIELD DECLARED;
}
}
可以看到item.asType().getKind()能够分辨控件id和int类型的区别,
我把加代码的那段换成如下,就是判断如果类型为INT就正常int赋值,如果类型为DECLARED就findViewById
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()));
后来通过实验,代码运行正常,
@TestActivity
public class MainActivity extends Activity {
@TestInt int a; @TestInt(value = 1) int b; @TestInt(1) int c; @TestInt(R.id.tv1) TextView tv1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TestMainActivity.setDefualt(this); setContentView(R.layout.activity_main); Log.v("zzw"," a:"+a+" b:"+b+" c:"+c); tv1.setText(" a:"+a+" b:"+b+" c:"+c); }
}
但是我还记得R.layout.activity_main也是int类型,我们应该能够使用注解来设置布局,这注解用在哪呢,我就用在TestActivity这个注解吧
那我就要改变TestActivity的代码,加个int的变量
@Target(ElementType.TYPE)[url=mailto:br/>@Retention(RetentionPolicy.CLASS)
@Retention(RetentionPolicy.CLASS)
int value() default 0;
}
然后在注解处理器里添加一行接收TestActivity的value值并给Activity设置布局的代码
TestActivity activity = typeElement.getAnnotation(TestActivity.class); if(activity == null){ continue; } bindViewMethodSpecBuilder.addStatement(String.format("activity.setContentView(%s)",activity.value()));
使用如下:
@TestActivity(R.layout.activity_main)
public class MainActivity extends Activity {
@TestInt int a; @TestInt(value = 1) int b; @TestInt(1) int c; @TestInt(R.id.tv1) TextView tv1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TestMainActivity.setDefualt(this); Log.v("zzw"," a:"+a+" b:"+b+" c:"+c); tv1.setText(" a:"+a+" b:"+b+" c:"+c); }
}
完整的注释处理器代码如下
@AutoService(Processor.class)
public class TestProcessor extends AbstractProcessor {
private Elements elementUtils;[url=mailto:br/>@Override
@Override
// 规定需要处理的注解
return Collections.singleton(TestActivity.class.getCanonicalName());[url=mailto:br/>}
@Override
}
@Override
相关文章推荐
- Android APT开发教程 五 使用注释完成findViewById和setContentView
- Android APT开发教程 六 使用注解替代setOnClickListener还有注释给String赋值
- android开发经验-findViewById(参数)的使用
- Android APT开发教程 六 使用注解替代setOnClickListener还有注释
- Android开发框架xUtils简介(附有不使用findViewById的方法)
- 求助 android开发中 如果两个控件的id相同 会怎样?如何使用findviewbyid ()寻找到?
- Android开发中ViewFlipper和ViewSwitcher使用GestureDetector完成切换
- Android开发学习之路-让注解帮你简化代码,彻底抛弃findViewById
- Android使用DataBinding代替findViewById
- Android版本:使用findViewById()用字符串/在一个循环
- Android解决使用findViewById时需要对返回值进行类型转换问题的辅助类
- Android基础入门教程——2.4.11 AutoCompleteTextView(自动完成文本框)的基本使用
- Android App开发中RecyclerView控件的基本使用教程
- Android使用Fragment,不能得到Fragment内部控件,findViewById()结果是Null--已经解决
- Android 注解的简单使用之省去findViewById()
- Android App开发中ViewPager组件的入门使用教程
- android通过反射代替findViewById的过多使用
- android 减少findViewById 的使用
- 注释参数opengl的surfaceview使用findViewById返回null问题解决
- android 使用泛型再也不写findViewById方法了