Android Kotlin Annotation Processer
Annotation Processer
注解处理器(Annotation Processer)是javac内置的注解处理工具,可以在编译时处理注解,让我们自己做相应的处理.比如生成重复度很高的代码,butterKnife就是借助Annotation Processer来生成findViewById的代码.
本文主要介绍Kotlin环境下如何使用.
Kotlin环境先要使用Annotation Processer需要注意一下几点
a.相关的模块语言必须是kotlin
b.依赖注解处理模块时需要使用kapt来依赖,否则不生效
首先新建一个空白的Android项目,开发语言要选择Kotlin

新建一个annotations模块,选择kotlin,这个模块存放所有的注解.

然后创建一个BindView的注解
package komine.libs.annotations
//表示该注解只存在于源码阶段
@Retention(AnnotationRetention.SOURCE)
//表示注解可以标记在字段上
@Target(AnnotationTarget.FIELD)
annotation class BindView(val viewId:Int = -1)
创建processer模块,用来处理注解

然后在main目录下创建resources\META-INF\services文件夹,并新建javax.annotation.processing.Processor文件

创建一个BindingProcessor类,并继承自AbstractProcessor,重写process方法
@SupportedSourceVersion(SourceVersion.RELEASE_8)
class BindingProcessor:AbstractProcessor() {
//它就表示我们要生成的那个文件
private lateinit var filer: Filer
override fun init(processingEnv: ProcessingEnvironment?) {
super.init(processingEnv)
filer = processingEnv!!.filer
}
override fun process(p0: MutableSet<out TypeElement>?, p1: RoundEnvironment?): Boolean {
println("annotation process...")
return true
}
//processor模块记得引用annotations模块
//返回要处理的注解
override fun getSupportedAnnotationTypes(): MutableSet<String> {
return mutableSetOf(BindView::class.java.canonicalName)
}
}
编辑javax.annotation.processing.Processor文件,将新建的类添加进去,之前的步骤如果没有出现错误的话,IDE应该会有提示

然后在app模块引入kapt插件,如果你的AS版本和我不一致,自己想办法引入kapt
plugins {
...
...
id 'kotlin-kapt'
}
然后在build.gradle引用processor和annotations模块
implementation project(path: ':annotations')
kapt project(path: ':processer')
最后在MainActivity中使用BindView注解

点击rebuild Project,如果配置没有问题,可以在build输出中看到打印的日志

接下来我们来实现butterKnife的findViewById功能
在app项目中新建一个Binding类,也可以放到其他模块
object Binding {
fun <T : Any> bind(target: T) {
try{
//获取类的名字,之后会通过代码动态生成该类
//因为只需要反射一次,所以性能几乎没有影响
val bindingClass = Class.forName(target::class.java.canonicalName + "Binding")
val constructor = bindingClass.getDeclaredConstructor(target.javaClass)
constructor.newInstance(target)
}catch (e:Exception){
e.printStackTrace()
}
}
}
然后回到processor模块,在process方法中去动态生成绑定类,首先引入implementation 'com.squareup:kotlinpoet:1.12.0'源文件生成工具,
你也可以手动生成.
override fun process(typeElement: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment?): Boolean {
//process方法会多次执行,导致出现Attempt to reopen a file for path错误,添加if判断
if(typeElement!!.isEmpty()){
return false
}
for (element in roundEnv!!.rootElements){
//获取包名
val packageName = element.enclosingElement.toString()
//获取当前类型的类名
val classStr = element.simpleName.toString()
//implementation 'com.squareup:kotlinpoet:1.12.0' class生成工具
//你也可以按照自己的方式来生成,不用生成工具
val className = ClassName(packageName,classStr + "Binding")
val codeBlockBuilder = CodeBlock.Builder()
//是否需要生成绑定文件
var needBinding = false
//遍历类中的所有成员
for (enclosedElement in element.enclosedElements){
//如果成员是字段
if(enclosedElement.kind == ElementKind.FIELD){
val bindView = enclosedElement.getAnnotation(BindView::class.java)
if(bindView != null && bindView.viewId != -1){
needBinding = true
//字段上有标注BindView注解
//这里的activity表示生成的类的构造函数中的参数名称,你也可以改成其他的,但要保持一致
codeBlockBuilder.addStatement("activity.${enclosedElement.simpleName} = activity.findViewById(${bindView.viewId})")
}
}
}
if(needBinding){
//生成Binding源文件
val file = FileSpec.builder(packageName,className.simpleName)
.addType(
TypeSpec.classBuilder(className)
.primaryConstructor(
FunSpec.constructorBuilder()
.addParameter("activity",ClassName(packageName,classStr)).build()
)
.addInitializerBlock(
codeBlockBuilder.build()
)
.build()
)
file.build().writeTo(filer)
}
}
return false
}
生成的文件在build/generated/source/kapt文件夹下

然后在MainActivity中绑定
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Binding.bind(this)
mTextView.text = "Binding"
}

源码:https://pan.baidu.com/s/19eBpHa-qDMpTEvHRbjq5ww 提取码:3939
Android Kotlin Annotation Processer的更多相关文章
- Java Android 注解(Annotation) 及几个常用开源项目注解原理简析
不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...
- 【转】深入浅出Android Support Annotation
[转自]http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0427/2797.html http://www.flysnow.org/201 ...
- import android.support.annotation.NonNull;报错
将import android.support.annotation.NonNull;换成import androidx.annotation.NonNull;
- android studio annotation 配置过程
参考了好些配置,发现总有这样,那样的问题. 环境:androidstudio 1.5 preview 2 sdk 6.0 1.首先新建一个android项目. 过程略 2.配置project的buil ...
- Android Kotlin —— 语言结合
2017 Google I/O 大会开始就宣布,将Kotlin语言作为安卓开发的一级编程语言. Kotlin 是一个基于 JVM 的新的编程语言,由 JetBrains 开发. Ko ...
- Android Kotlin适用小函数
都是一些Android适用的Kotlin小函数. 1.点击空白隐藏键盘 //点击空白隐藏键盘 override fun onTouchEvent(event: MotionEvent): Boolea ...
- Android -------- kotlin插件神器Json直接生成javaBean
这是一个data class从JSON字符串生成Kotlin 的插件,换句话说,是一个将JSON字符串转换为Kotlin data class(Json到Kotlin)的插件 在使用Kotlin进行开 ...
- Android Kotlin Jetpack Compose UI框架 完全解析
前言 Q1的时候公司列了个培训计划,部分人作为讲师要上报培训课题.那时候刚从好几个Android项目里抽离出来,正好看到Jetpack发布了新玩意儿--Compose,我被它的快速实时打包给吸引住了, ...
- Android Kotlin协程入门
Android官方推荐使用协程来处理异步问题.以下是协程的特点: 轻量:单个线程上可运行多个协程.协程支持挂起,不会使正在运行协程的线程阻塞.挂起比阻塞节省内存,且支持多个并行操作. 内存泄漏更少:使 ...
随机推荐
- 为什么要使用TypeScript(Why Typescript?)
客观原因 静态类型. 在编译期即可进行静态类型分析, 减少JS运行时类型错误. 语法功能强大 对于大型项目具有更好构建机制,加入了类.接口.泛型.模块等概念. 兼容JavaScript 与现存的Jav ...
- 怎么理解相互独立事件?真的是没有任何关系的事件吗?《考研概率论学习之我见》 -by zobol
1.从条件概率的定义来看独立事件的定义 2.从古典概率的定义来看独立事件的定义 3.P(A|B)和P(A)的关系是什么? 4.由P(AB)=P(A)P(B)推出"独立" 5.从韦恩 ...
- NLog自定义Target之MQTT
NLog是.Net中最流行的日志记录开源项目(之一),它灵活.免费.开源 官方支持文件.网络(Tcp.Udp).数据库.控制台等输出 社区支持Elastic.Seq等日志平台输出 实时日志需求 在工业 ...
- 关于Vue Element组件el-checkbox与el-select默认选中值的几点注意事项
el-select 示例: 代码: <el-select v-model="doc.zhic" placeholder="请选择"> <el- ...
- ASP.NET MVC之读取服务器文件资源的两种方式
初次认识asp.net mvc时,以为所有文件都需要走一遍路由,然后才能在客户端显示, 所以我首先介绍这一种方式 比如说:我们在服务器上有图片: ~/resource/image/5.jpg 我们就需 ...
- WPF双滑块控件以及强制捕获鼠标事件焦点
效果 概述 最近有个小需求要用双滑块表示一个取值范围,于是就简单做了个用户控件,在此记录下. 使用矩形Rectangle表示范围,椭圆Ellipse表示滑块,使用Canvas控制滑块的左右移动. 椭圆 ...
- ajax传递参数与controller接收参数映射关系
将ajax的参数传递至后台controller时,data 中的参数名要与controller中的形参保持一致. 前端ajax代码: 1 $.ajax({ 2 url:"/doLogin&q ...
- npm相关知识整理
语义化版本 major: 重大变化,不兼容老版本 minor: 新增功能,兼容老版本 patch: 修复bug,兼容老版本 依赖版本号 * 匹配最新版本的依赖 ^ 匹配最近的大版本依赖,比如^1.2. ...
- 小米社区APP深度体验
小米社区APP深度体验 版本:3.0.210928 BUG 1,在暗黑模式下,会员一栏中的成就等级小字未作深色模式调整,从而造成文字难于识别. 2,在暗黑模式下,会员页中底部的会员产品首页视觉没有完美 ...
- centos7 netstat command not found
只需要执行: yum install net-tools 就ok.