
在上一篇文章中,我们学习了如何在运行时自定义注释功能,并简单地实现了类似于ButterKnife的功能. 但是通常情况下,我们使用ButterKnife或Eventbus,AndroidAnnotations,它们都在编译时使用了注释功能.
编译时注释和运行时注释之间有什么区别?实际上,它并不大,主要是由于性能问题. 运行时批注主要取决于反射. 反射效率比原始反射效率慢,因此在内存较少且CPU较差的计算机上会出现停滞. 编译期间的注释根本不会出现此问题,因为它是通过我们的编译过程(java->类)中的某些注释生成的,以动态生成某些类或文件,因此与我们的APK操作无关. 自然没有性能问题. 因此,如果注释功能通常用于著名的开源项目,则通常在编译时使用注释
本文的最终演示已上传到github,欢迎大家关注,关注
那么多的烦恼,让我们学习如何自己实现编译时注释功能,因为我认为您每天都过多使用这种框架,因此无需教您如何使用它
首先创建一个as项目,对此无话可说. 然后,我们创建一个注释库. 该库的知识太大. 我们不能使用常规的Android库. 相反,我们必须使用Java库,因为我们需要使用javase中的内容,而android.jar中缺少相应的部分. 当然,您不必担心手机中使用的这些东西,因为我们只需要在计算机上对其进行编译

建立Java模块目录结构后
这里还有另一个地方需要注意. 我们需要在库的build.gradle中配置java的版本,这与RetroLambda类似. 在这里,我无法报告一系列错误. 只需去看看ButterKnife如何编写它,然后将它放在我这一边即可尝试并完美解决

apply plugin: 'java'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
请不要在此处使用1.8,因为只有android N支持java8,因此如果您编写1.8,则必须使用buildToolsVersion作为24.0.0
这样,就可以构建项目,并将代码写在下面
1个注释类的实现
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.CLASS)
public @interface PrintInject {
int[] value();
}
阅读以上文章的朋友应该能够一目了然
2实现AbstractProcessor并在其中重写处理方法
AbstractProcessor在哪里神圣? apt(注释处理工具)在编译时自动查找从AbstractProcessor继承的所有类,然后调用它们的process方法进行处理,从而使其能够在编译过程中执行代码

@SupportedAnnotationTypes("com.example.PrintInject")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class PrintInjectProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Messager messager = processingEnv.getMessager();
for (TypeElement te : annotations) {
for (Element e : roundEnv.getElementsAnnotatedWith(te)) {
messager.printMessage(Diagnostic.Kind.NOTE, "Printing: " + e.toString());
}
}
return true;
}
}
我在这里需要详细解释,因为稍后将使用相似的对象来完成更复杂的功能
SupportedAnnotationTypes: 用于指示注释处理器支持的注释的注释类型. 这指的是我们刚刚定义的PrintInject类
SupportedSourceVersion: 用于指示注释处理器支持的JAVA版本
processingEnv: 注释处理工具框架将提供一个工作环境processingEnvjava中注释编译时,以便它可以使用框架提供的功能来编写新文件,报告错误消息并查找其他实用程序.
TypeElement: 我们定义的所有不同类型的注释,例如此处应返回PrintInject.class
getElementsAnnotatedWith: 返回所有具有相应注释类型的元素. 如果您写一些此类注释,则Set的长度将尽可能长
printMessage: 使用messager直接打印不同类型的不同消息. 类似于Log,这里是Kind,有NOTE,ERRPR,WARNING等,我们通常会在Android Studio控制台中看到各种信息,其中一些信息已经打印出来

现在我们几乎可以理解这些代码行的含义: 打印有关带注释元素的信息
3服务注册文件(META-INF / services / javax.annotation.processing.Processor)
为了便于执行编译器注释工具以使其能够运行PrintInjectProcessor,必须将其注册到服务文件中. 处理器的位置写在文件中
com.example.PrintInjectProcessor

javax.annotation.processing.Processor文件位置
现在可以编译,您可以获取jar包


获取已编译的jar包
就像普通的jar一样,只需将其直接复制到libs文件夹下
@PrintInject({1})
public class MainActivity extends AppCompatActivity {
@PrintInject({3})
TextView textview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@PrintInject({2})
public void click() {
Toast.makeText(this, "HHH", Toast.LENGTH_SHORT).show();
}
}
我们分别为类型,字段和方法添加了注释. 此时,我们可以开始编译,并且gradle构建将带您
注: Printing: com.rg.annotationdemo.MainActivity
注: Printing: textview
注: Printing: click()

编译结果
看到它,注释的元素信息就这样打印出来
作为第一个项目,我们首先简要了解一下此过程java中注释编译时,并使其执行编译中的一些代码. 在下一篇文章中,我们将做一个真正的工作. 我将用宏阳的演示进行解释. 我不知道此演示是否可以运行,因为他的项目在Eclipse上,并且Android Studio上的实现步骤与Eclipse不同. 最重要的是该演示没有评论,没有评论,没有评论,因此非常适合我们练习手
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-178489-1.html
让女性普便比男性更有钱