close
当前位置: 物联网在线 > 技术文库 > android >

在 Android Studio 中使用 Annotation Processor

Java 的 Annotation Processor 是非常有用的功能,很多常用的库和框架都使用了 Annotation Processor 来生成代码,比如 Butter Knife 就用来生成 findViewById 等代码。

对于一些模板代码使用 Annotation Processor 来自动生成可以提高编写代码的效率和质量,手工编写毕竟容易出现纰漏,工具自动生成是有质量保证的。本文是由 Aitor Viana 编写的如何在 Android Studio 中使用 Annotation Processor 的介绍。

Annotation Processor 主要涉及 3 部分,注解本身(Annotation)、注解处理器(Annotation Processor)以及 在 Android Studio 中如何使用注解处理器。

本文通过如何使用注解来自动生成 Parcelable 接口的代码。

注解

注解就不用详细介绍了,在 Android 编码中应该经常使用。自定义一个表示需要自动生成 Parcelable 的注解: AutoParcel。

在 Android Studio 中创建一个 Java module,名字为 library 。在这个模块中创建这个自定义的 AutoParcel 注解类:

在 Android Studio 中使用 Annotation Processor

package com.example.autoparcel; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) // 代表在类级别上才能使用该注解 @Retention(RetentionPolicy.SOURCE) // 代表该注解只存在源代码中,编译后的字节码中不存在 public @interface AutoParcel {}  

由于 AutoParcel 只在源代码中存在,编译后没有在字节码中,所以最最终的运行时是没有影响的。

由于这个 library 库需要在 Android 项目中引用,所以需要修改其 gradle 文件制定编译的 Java 语言版本(library/build.gradle ):

applyplugin: 'java'   // This module will be used in Android projects, need to be // compatible with Java 1.7 sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7   dependencies {     ... }   注解处理器

注解处理器的功能就是用来读取代码中的注解然后来生成相关的代码。

创建一个 Java module 名字为 “compiler”。 该模块在编译的时候,来获取哪些类使用了 AutoParcel 注解,然后把继承这些类实现 Parcelable 的代码。该模块并不在 Android 项目中引用,只存在于编译的时候。所以这个模块的 Java 版本号可以随意指定(Java 8 、9)。

创建一个 AutoParcelProcessor 类来处理注解:

在 Android Studio 中使用 Annotation Processor

package com.example.autoparcel.codegen; @SupportedAnnotationTypes("com.example.autoparcel.AutoParcel") public final class AutoParcelProcessor extends AbstractProcessor {   @Override   public boolean process(           Set<? extends TypeElement> annotations,           RoundEnvironmentenv) {     ...   } }  

对于该类有几点要求:

1. 需要继承至 AbstractProcessor

2. 需要使用类的全称(包含包名)来指定其支持的注解类型(com.example.autoparcel.AutoParcel)

3. 实现 process() 函数,在该函数中来处理所支持的注解类型并生成需要的代码。

下面只是介绍了实现 process() 函数的关键部分,完整代码参考最后的项目。

如果没有其他处理器需要继续处理该注解,则 process() 返回 true。针对我们这个情况,只有 AutoParcelProcessor 需要处理 AutoParcel 注解,所以该函数返回 true。

package com.example.autoparcel.codegen; ... @Override public boolean process(       Set<? extends TypeElement> annotations,       RoundEnvironmentenv) {       Collection<? extends Element> annotatedElements =             env.getElementsAnnotatedWith(AutoParcel.class);     List<TypeElement> types =           new ImmutableList.Builder<TypeElement>()             .addAll(ElementFilter.typesIn(annotatedElements))             .build();       for (TypeElementtype : types) {         processType(type);     }       // 返回 true ,其他处理器不关心 AutoParcel  注解     return true; } private void processType(TypeElementtype) {     String className = generatedSubclassName(type);     String source = generateClass(type, className);     writeSourceFile(className, source, type); } private void writeSourceFile(         String className,         String text,         TypeElementoriginatingType) {     try {         JavaFileObjectsourceFile =             processingEnv.getFiler().                 createSourceFile(className, originatingType);         Writerwriter = sourceFile.openWriter();         try {             writer.write(text);         } finally {             writer.close();         }     } catch (IOException e) {// silent} } ...  
(责任编辑:ioter)

用户喜欢...

Android Weekly #276 安卓开发周刊 中文版

您是否了解过Android的Lifecycle-Aware库?(android.jlelse.eu) 我们如何了解Lifecycle-Aware库代码? Nishant Srivastava展示了可以跟踪活动或Lifecycle-Aware的Lifecycle Arch组件的片段,并相应地调整其行为。 为Mos...


Android Weekly #275 安卓开发周刊 中文版

MapMe — Android地图适配器 (medium.com) Josh Burton介绍MapMe,是一个用Kotlin编写的Android库,可以将适配器模式带到地图上。 赞助 CloudRail - 连接到API 10x更快 (cloudrail.com) 当我们用单一的界面连接到所...


使用Android Studio开发可独立运行(runnable)混淆过的Jar程序

之前开发Java程序一直都是使用Eclipse 开发Jar程序,现在开发基本上都已经弃用Eclipse了,但是有时偶尔开发个小的Jar程序,还要切换回去好麻烦,刚好前几天有人问几个相关的问题,就顺便整...


Android Weekly #274 安卓开发周刊 中文版

探索Android Oreo上的别后执行限制(medium.com) 在这篇文章中,Joe Birch解释了关于Android Oreo在后台运行服务的变化。 non-Time领主的time – 第5部分 (blog.stylingandroid.com) Mark Allison继续分析JSR 310 date和...


Android Weekly #273 安卓开发周刊 中文版

开源你的Android代码(android.jlelse.eu) 通过您的开源Android代码,您将(希望地)为Android社区提供有价值的代码,收到建设性的反馈,并与您最初建立的内容进行协作从而使您的代码变得更好。这...


Android Weekly #272 安卓开发周刊 中文版

Android Dev 101:每个初学者都应该知道的一些做法() 看一些初学者或媒介等级开发人员(不要错过任何人)应该知道的一些做法,以便更好地摆脱Android框架。 99.9% crash free sessions (medium.com) Chr...


Android Weekly #271 安卓开发周刊 中文版

依赖注入检查(medium.com) 在本文中,MihályNagy引入了依赖注入检查,一种开源注释处理器,可帮助您解决一些出现在所有JSR 330 DI库中常见的问题。 使用Android Studio插件提高效率 (blog.mindorks.com...


Android Weekly #270 安卓开发周刊 中文版

带有RxJava2的SOLID Android分析 (medium.com) 在这篇文章中,Aris Papadopoulos将解释如何正确创建一个分析系统,同时遵循SOLID原则,并使用RxJava2来解决问题。 (blog.stylingandroid.com) Java中的编程时间很难...


Android内存泄漏思考

Android内存泄漏是一个经常要遇到的问题,程序在内存泄漏的时候很容易导致OOM的发生。那么如何查找内存泄漏和避免内存泄漏就是需要知晓的一个问题,首先我们需要知道一些基础知识。...


Android Weekly #269 安卓开发周刊 中文版

在Google上快速提出操作 () Wolfram Rittmeyer分享了开始在Google上快速创建操作所需的所有信息(为了家庭与助理)。 RxJava中的错误处理(rongi.github.io) 一旦开始编写RxJava代码,你就会意识到有些事...