Kotlin 代码的可空问题
能够看如下的代码:
这儿的age 是一个可空的,当你用ksp注解处理器生成代码时就会报错了
能够看下报错信息:
他说这儿需要的是一个Int,可是你传的值是一个Int? 那明显这是一个kotlin代码 专属的一个问题了
要解决这个问题其实也不难
用这种办法即可解决:
那剩余的 其实便是 要想办法判别一下 这个变量的类型 到底是不是可空的
好在ksp中的特点 有办法能够直接拿到是否为空的符号
KSPropertyDeclaration.type.resolve().isMarkedNullable
有了这个其实就很简略了,无非便是判别一下 假如可空,那就换一下写法,仅此而已。 代码就不上了
添加private校验
这个其实便是因为Arouter 的机制 原因,运用autowried注解的变量 有必要对错private的
所以假如你断定了对错private的 记得让编译提示 有用的信息 便利开发者
if (ksproperty.modifiers.contains(Modifier.PRIVATE)) {
throw IllegalAccessException(
"The inject fields CAN NOT BE 'private'!!! please check field [" +
ksproperty.simpleName.asString() + "] in class [" + className + "]"
)
}
拦截器
之前咱们尽管完成了界面跳转以及值传递,可是还漏掉了一个拦截器的机制没有处理,现在补上去
拦截器的完成 应该说很简略了 取一下对应的注解
然后生成一下对应的类即可
这儿就不具体解释了, 没什么难点 仅有要留意的便是 留意loadInto参数的生成
@OptIn(KotlinPoetKspPreview::class)
override fun process(resolver: Resolver): List<KSAnnotated> {
// 这儿是取module name 一般情况下module name的方式都是
// A-B, 这儿就过滤掉特殊符号,转成AB 即可
var moduleName = options[Consts.KEY_MODULE_NAME]
if (moduleName.isNullOrEmpty()) {
logger.warn(" u must set ${KConstants.kspArgHint}")
} else {
moduleName = moduleName.replace("[^0-9a-zA-Z_]+".toRegex(), "")
}
val symbol = resolver.getSymbolsWithAnnotation(Interceptor::class.qualifiedName!!)
val elements = symbol.filterIsInstance<KSClassDeclaration>().toList()
val map = mutableMapOf<Int, KSClassDeclaration>()
elements.forEach { ks ->
val annotation = ks.findAnnotationWithType<Interceptor>()
val key = annotation!!.priority
map[key] = ks
}
// 假如没有 那就直接返回 不要走剩余的流程了
if (map.isNullOrEmpty()) {
return emptyList()
}
// 仅有要留意的便是这儿了 留意参数的类型构造
val parameterSpec = ParameterSpec.builder(
"interceptor",
MUTABLE_MAP.parameterizedBy(
INT,
Class::class.asClassName().parameterizedBy(
WildcardTypeName.producerOf(
Consts.IINTERCEPTOR.quantifyNameToClassName()
)
)
).copy(nullable = true)
).build()
val className = "ARouter$$Interceptors$$$moduleName"
val funSpec = FunSpec.builder("loadInto").addModifiers(KModifier.OVERRIDE)
.addParameter(parameterSpec)
funSpec.addStatement("if(interceptor == null) { return }")
map.forEach { (key, ksClassDeclaration) ->
// interceptor.put(7, Test1Interceptor::class.java)
funSpec.addStatement(
"interceptor.put($key, %T::class.java)",
ksClassDeclaration.toClassName()
)
}
val file = FileSpec.builder("com.alibaba.android.arouter.routes", className)
.addType(
TypeSpec.classBuilder(className).addSuperinterface(
ClassName(
"com.alibaba.android.arouter.facade.template",
"IInterceptorGroup"
)
).addFunction(funSpec.build()).build()
)
.build()
file.writeTo(codeGen, false)
return emptyList()
}
extra
这个功用其实很多用Arouter的人都不知道咋用,
比如这儿 设置了一个extras 的值 为110
我在这儿
能够获得这个extra的值, 通常能够利用这个extra 作一些开关的效果
最终生成的代码其实便是RouteMeta这个build 中最终一个参数
用ksp注解处理器的时候 这儿不要忘记完成extra, 这儿代码就不上了,之前的文章已经介绍过如何完成RouteMeta的build语句了,无非便是取一下对应extra的值而已
到这儿 整体上arouter的ksp 的注解处理器就完成结束了。