自定义运行时注解、编译时注解[ButterKnife原理探析]

本文面向了解注解基础的读者,深入探讨自定义注解,包括运行时注解的创建、注解处理器的实现,以及编译时注解的流程与应用。通过实例,解析ButterKnife的工作原理,指导如何在Android Studio中自定义注解库。
摘要由CSDN通过智能技术生成

本篇博文针对具备注解基础的读者,主要讲解如何进行自定义注解。关于注解的具体基础知识点,网上这方面的学习资料非常多,可自行学习。

注解目前在主流的框架,比如Android中的Glide、Retrofit;Java Web方向的Spring等都有大量的使用。在给开发者带来巨大方便的同时,作为开发者有必要了解学习注解及其自定义,甚至可以自定义自己的注解库呦。

以下分析均在Android Studio中进行;

1、基础


上图来源于网络。感谢。上图是对Java注解知识点的总结,已经十分的全面了。如果你只是想自定义一个运行时的注解及处理器,上述知识点已经足够。但是如果你想要自定义一个编译型注解,那你还需要学习更多东西,比如AbstractProcessor、APT、JavaPoet等等,稍后会介绍。

2、区别

运行时注解与编译时注解的区别是什么呢?
a)保留阶段不同。运行时注解保留到运行时,可在运行时访问。而编译时注解保留到编译时,运行时无法访问。
b)原理不同。运行时注解是Java反射机制,而编译时注解通过APT、AbstractProcessor。
c)性能不同。运行时注解由于使用Java反射,因此对性能上有影响。编译时注解对性能没影响。这也是为什么ButterKnife从运行时切换到了编译时的原因。
d)产物不同。运行时注解只需自定义注解处理器即可,不会产生其他文件。而编译时注解通常会产生新的Java源文件。

3、运行时注解

相对于编译时注解,运行时注解要简单的多。运行时注解的自定义只有两个步骤:
自定义注解 + 注解处理器(会用到java反射机制);

3.1、自定义运行时注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimeBind {
    int value();
}
RetentionPolicy.RUNTIME:表明这是一个运行时的注解,如果是编译时注解,则应该是RetentionPolicy.CLASS。
ElementType.FIELD:表明该注解是用于域的。

3.2、自定义注解处理器

public class RuntimeAnnotationProcessor {
    public static void bind2(Activity activity){
        if (activity==null) return;
      Field[] fields =   activity.getClass().getDeclaredFields();
        if (fields == null || fields.length == 0) return;
        for(int i=0;i<fields.length;i++){
            if (fields[i].isAnnotationPresent(RuntimeBind.class)){
                int resId  = fields[i].getAnnotation(RuntimeBind.class).value();
                fields[i].setAccessible(true);
                try {
                    fields[i].set(activity,activity.findViewById(resId));
                    fields[i].setAccessible(false);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    fields[i].setAccessible(false);
                }
            }
        }
    }
}
可以看到,代码量还是很小的。首先,我们通过反射获取到当前Activity都有哪些字段,然后再判断每个字段是不是在使用RuntimeBind注解,如果使用了,则获取该注解的值,同时将该注解的值赋值给对应的字段就可以了。

3.3、使用运行时注解处理器

public class MainActivity extends AppCompatActivity {

    @RuntimeBind(R.id.tv_runtime)
    TextView tv_runtime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       RuntimeAnnotationProcessor.bind2(this);
        tv_runtime.setText("运行时注解成功");
    }
}
在使用的时候,只需要调用RuntimeAnnotationProcessor.bind2(..)即可完成繁琐的findViewById工作了。是不是很方便。但是,如果存在大量的通过运行时注解,则在一定程度上会影响程序的性能的。因此,编译时注解的优势就发挥出来了。

4、编译时注解

编译时注解总体结构:编译时注解 + 注解处理器(基于AbstractProcessor) + APT + JavaPoet(自定义Java源文件会用到)  + auto-service(处理器注册);

4.1、基础准备

a)什么是APT?
APT(Annotation Processing Tool)是javac内置的工具,用于在编译时期扫描和处理注解信息。它对源代码文件进行检测找出其中的Annotation,根据注解自动生成代码(调用注解处理器的Process方法生成源文件)。 Annotation处理器在处理Annotation时可以根据源文件中的Annotation生成额外的源文件和其它的文件(文件具体内容由Annotation处理器的编写者决定),APT还会编译生成的源文件和原来的源文件,将它们一起生成class文件。
b)APT插件(工具)
android-apt:由一位开发者自己开发的apt框架,源代码托管在这里,随着Android Gradle 插件 2.2 版
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值