自定义一个基于注解的路由框架
定义注解类
- 新建一个模块 router_annotations
- 在 router_annotations 目录中创建 build.gradle
1 | apply plugin: "kotlin" // 使用 kotlin |
- 定义注解类
1 | package com.example.test |
定义注解处理器模块
- 新建一个模块 router_compile
- 在 router_compile 目录中创建 build.gradle
1 |
|
在注解处理器模块,如果使用kotlin写注解处理器代码,需要引用 kotlin-kapt
这个插件implementation "com.google.auto.service:auto-service:1.0-rc6"
使用google的一个注解框架。
同时还要加上 kapt "com.google.auto.service:auto-service:1.0-rc6"
。 这是kotlin的写法,如果是java,需要换成annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'
- 编写注解处理器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class DestinationProcessor : AbstractProcessor() {
private val TAG = "DestinationProcessor"
override fun process(
set: MutableSet<out TypeElement>,
roundEnvironment: RoundEnvironment
): Boolean {
if (roundEnvironment.processingOver()) {
return false
}
println("$TAG >>>> process start")
println(set)
val destinationClasses = roundEnvironment.getElementsAnnotatedWith(Destination::class.java)
println(TAG + " " + destinationClasses.size)
if (destinationClasses.size < 1) {
return false
}
for (element in destinationClasses) {
val typeElement = element as TypeElement
val destination = typeElement.getAnnotation(Destination::class.java)
?: continue
val url = destination.url
val className = typeElement.qualifiedName
println("$TAG $url $className")
}
println("$TAG >>>> process finish")
return true
}
override fun getSupportedAnnotationTypes(): MutableSet<String> {
return mutableSetOf(
Destination::class.java.canonicalName
)
}
}
@AutoService(Processor::class)
是固定写法
AbstractProcessor
继承这个抽象类。
重写getSupportedAnnotationTypes
方法,返回需要处理的注解。
重写process
方法,处理注解信息。 返回值为true表示已处理这个注解,相同的注解不会再被其他注解处理器处理。roundEnvironment.processingOver()
表示之前已经有处理过一轮,此时roundEnvironment.elements.size==0
不是很明白gradle为什么会执行多轮。。。
在本地使用注解
1 | implementation project(":router_annotations") |
将注解处理器打包成组件并发布
在最外层的 build.properties 中写通用参数
1
2
3POM_URL=../repo // 发布的仓库地址,这里是本地
GROUP_ID=com.example.test // group
VERSION_NAME=1.0.0 // 版本在 router_annotation 和 router_compile 中写 group_id
1
2
3
4
5// 在 router_annotation build.properties
POM_ARTIFACT_ID=router-test-annotation
// 在 router_compile build.properties
POM_ARTIFACT_ID=router-test-processor编写发布脚本 maven-publish.gradle
1 | apply plugin: 'maven' // 引入maven插件 |
注意有一个 pom.whenConfigured { pom -> ...
的代码,这是因为 router_compile 应用到了 router_annotations 模块。如果不做处理,发布之后, router_comiple 模块是找不到 router_annotations 的正确位置和版本的。所以要强制制定
执行发布任务
1 | ./gradlew :router_compile:uploadArchives |
我们设置的 POM_URL=../repo
所以最终会在项目的repo目录里生成aar包。
使用发布后的组件
- 首先,moven本地仓库地址加入到工程里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15buildscript {
repositories {
maven { url uri('/Users/bytedance/code/test/repo') }
google()
mavenCentral()
}
}
allprojects {
repositories {
maven { url uri('/Users/bytedance/code/test/repo') }
google()
mavenCentral()
}
}
buildscript.repositories 和 allprojects.repositories 都要加,这样才会应用到所有子工程
在app模块里引用组件
1
2implementation "com.example.test:router-test-annotation:1.0.0"
kapt "com.example.test:router-test-processor:1.0.0"gradle版本的区别
在 gradle 7.+ 版本有很多东西不兼容,上述实现只有在 gradle 6.+ 的版本有效。 gradle 的版本升级和项目创建还是要谨慎一些。