注解(反射+APT)整理(附带脑图)

本人整理脑图


注解扫盲和自定义注解
带你从头到尾玩转注解
这两篇是我之前学习的时候看的博客,作者整理的很详细了。
我为了加深印象,自己又整理了个脑图,喜欢看图的可以看看本人整理脑图,个人喜欢看图说话,更直观一点。


编译时注解和运行时注解的区别

在现在市面上大多数的注解举例的时候,都是参照ButterKnife,然后告诉你怎么通过注解实现setContentView和FindViewByID。使用的呢也是两种方法:

  • 运行时注解(借助反射机制实现)
  • 编译时注解(APT-Annotation Processor Tool)

看着好像不管哪一种都可以,那么具体的实际运用中我们应该怎么选呢?
如果你有自己实现一遍你应该有一个直观的感受:

  • 反射只能使用本身已有的方法。因为反射的本质就是:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。
  • 而APT是生成我们自己的方法,可以做到无中生有。
  • 所以说:APT > 反射。

JavaPoet导包import遇到的问题

官方文档
官方文档写的很清楚,它的定义是:JavaPoet is a Java API for generating .java source files。
这里说一下我遇到的问题:
当我想要实现自定义的ButterKnife时,我可以很简单的实现findViewById。但是我需要给View添加点击事件的时候遇到了问题:

//添加findviewByID的方法
bindViewMethodSpec.addStatement(
                                String.format("targetActivity.%s = (%s) targetActivity.findViewById(%s)"
                                        , childElement.getSimpleName()
                                        , ClassName.get(childElement.asType()).toString()
                                        , bindView.id()));

通过上面的代码,我们很自然的想到,那我添加点击事件不就是:

 bindViewMethodSpec.addStatement(
    String.format("targetActivity.%s.setOnClickListener(targetActivity)"
       , childElement.getSimpleName()))

但是我没有,我使用的办法是:

bindViewMethodSpec.addStatement(
    String.format("targetActivity.%s.setOnClickListener((View.OnClickListener)targetActivity)"
           , childElement.getSimpleName()));

哈哈,结果编译不过去(智障),原因是没有View的import:

程序包View不存在

所以这里已经不是我的方法智障不智障的问题了,而是我们怎么通过Javapoet导包的问题了。
我查看了Javapoet的文档,参考了它的导包,总结出来两种导包的方法和三种解决这个问题的方法
第一种:

 ClassName arrayList3 = ClassName.get("android.view", "View");
bindViewMethodSpec.addStatement(
         String.format("targetActivity.%s.setOnClickListener(( %s.OnClickListener)targetActivity)"
                    , childElement.getSimpleName()
                      , arrayList3)
                  );

第二种:

 ClassName arrayList3 = ClassName.get("android.view", "View");
bindViewMethodSpec.addStatement(
   String.format("targetActivity.%s.setOnClickListener(( $T.OnClickListener)targetActivity)"
               , childElement.getSimpleName())
                   , arrayList3
           );

这两种是很相似的办法,只不过一个的通过String.format来拼接,一个是通过addStatement拼接。
下面这个就是我说的不需要导包解决的方法:
第三种:

bindViewMethodSpec.addStatement(
    String.format("targetActivity.%s.setOnClickListener((android.view.View.OnClickListener)targetActivity)"
        , childElement.getSimpleName()));

是的,你没有看错,就是全路径!!!
在这里贴出官方的方法,说实话我看的第一遍是没找到方法的,我是试了各种办法都不行的时候,最先想到的全路径的写法,而且百度的时候也没有具体的写法。在第二天又看的时候才看到,可能是当时没有静下心吧。。。

ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
ClassName list = ClassName.get("java.util", "List");
ClassName arrayList = ClassName.get("java.util", "ArrayList");
TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);

MethodSpec beyond = MethodSpec.methodBuilder("beyond")
    .returns(listOfHoverboards)
    //下面这行是重点,在之前我一直以为是上面的return,然后跟ParameterizedTypeName.get方法死磕不出来才看到的下面。
    .addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)
    .addStatement("result.add(new $T())", hoverboard)
    .addStatement("result.add(new $T())", hoverboard)
    .addStatement("result.add(new $T())", hoverboard)
    .addStatement("return result")
    .build();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值