KotlinPoet初体验(一)

585 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

KotlinPoet

之前的文章提到过一次JavaPoet,它是用来生成java代码的三方库。他还有kotlin版的KotlinPoet,甚至dart版的DartPoet。本文主要介绍kotlinpoet,其实这三个库API都差不多。

咋一看好像没什么用,但是当你想要生成一些模板代码的时候还是非常好用的。何时使用它,全凭想象力。例如:

1.你可以用它来生成MVP或是MVVM框架模板代码;
2.你也可以结合kapt或是ksp在编译时期根据注解生成类,运行时再用反射调用(很多三方库都是这样操作的);
3.你还可以像我之前文章提到过用它来处理一些工作量大,但编码格式化、机械化的工作。

常用API介绍

生成结果:

package com.example.poet

import kotlin.String
import kotlin.Unit

public class HelloWord {
  public fun testMethod(name: String): Unit {
    println("""Hello, $name""")
    println("Hello $name")
  }
}

KotlinPoet代码:

fun buildTestClass(): FileSpec {
    return FileSpec.builder("com.example.poet", "HelloWord")
        .addType(
            TypeSpec.classBuilder("HelloWord")
                .addFunction(
                    FunSpec.builder("testMethod")
                        .addModifiers(KModifier.PUBLIC)
                        .addParameter("name", String::class)
                        .addStatement("println(%P)", "Hello, \$name")
                        .addCode("println(\"Hello \$name\")")
                        .build()
                )
                .build()
        )
        .build()
}

buildTestClass().writeTo(File(path))

  • FileSpec.builder(packageName, fileName)构建一个文件,传入包名和文件名
  • TypeSpec.classBuilder("HelloWord")构建一个类,传入类名
  • FunSpec.builder("testMethod")构建一个方法,传入方法名

可以看到KotlinPoet是采用建造者模式,去构造文件、类、方法、参数等元素。使用起来还是较为简单。

整体结构有一个大致了解后,接下来介绍这些builder的具体用法。

FileSpec.builder


FileSpec.builder(packageName, "HelloWord")
        .addImport("android.os","Bundle")
        .addFunction(FunSpec.builder("outMethod").build())
        .addType(
            TypeSpec.classBuilder("HelloWord")
            .build()
        )
        .build()

addImport手动添加import
addFunction添加顶级函数
addType为该文件添加类

TypeSpec.xxxBuilder

TypeSpec不止可以构建类,它有多种builder。classBuilder、enumBuilder、annotationBuilder、companyObjectBuilder、objectBuilder等。
先来看看TypeSpec.classBuilder的API吧,其他几种builder用法都差不多。

TypeSpec.classBuilder("HelloWord")
    .addAnnotation(HiltAndroidApp::class)
    .addModifiers(KModifier.PROTECTED)
    .addKdoc("test")
    .superclass(Activity::class)
    .addSuperinterface(View.OnClickListener::class)
    .addFunction(
        FunSpec.builder("testMethod")
            .build()
    )
    .primaryConstructor(
        FunSpec.constructorBuilder()
            .build()
    )
    .build()

addAnnotation添加注解
addModifiers添加可见修饰符
addKdoc添加注释
superclass声明该类的父类
addSuperinterface实现接口
primaryConstructor主构造函数

生成的代码:

/**
 * test
 */
@HiltAndroidApp
protected class HelloWord() : Activity(), View.OnClickListener {
  public fun testMethod(): Unit {
  }
}

FunSpec.builder

val frameLayout = ClassName("android.widget", "FrameLayout")

FunSpec.builder("onCreate")
                        .addModifiers(KModifier.OVERRIDE)
                        .addParameter("savedInstanceState", Bundle::class.asClassName().copy(nullable = true))
                        .addAnnotation(Inject::class)
                        .addStatement("super.onCreate(savedInstanceState)")
                        .addCode("return ")
                        .addCode("FrameLayout(this)")
                        .returns(frameLayout)
                        .build()

addParameter方法入参
addStatement方法内容,会自动换行
addCode不会自动换行
returns返回参数,传入返回类型
ClassName("android.widget", "FrameLayout")可手动声明引入类型,会自动导包

生成代码:

@Inject
public override fun onCreate(savedInstanceState: Bundle?): FrameLayout {
  super.onCreate(savedInstanceState)
  return FrameLayout(this)
}

(这里只是举个例子,请忽略我的语法错误>v<)

OK,API就介绍到这里,我这里只是简单的介绍了一些常用的,如果需要了解更多用法,请上官网查阅KotlinPoet