【Android项目】KMMV项目随笔


项目学习过程中的一些随笔记录

一. Kotlin Symbol Processors使用 (KSP框架)

1. 使用教程

1.1 注册KOTLINMVVMPROCESSORPROVIDER以及引入依赖

在这里插入图片描述

com.catchpig.ksp.compiler.provider.KotlinMvvmProcessorProvider
implementation(libs.kotlinpoet.ksp)

1.2 实现 KotlinMvvmProcessorProvider 和 KotlinMvvmProcessor

✅ SymbolProcessorProvider 的作用

  • 创建 SymbolProcessor 实例:编译器在编译过程中会调用 create() 方法来获取一个 SymbolProcessor 实例
  • 作为 KSP 处理器的注册入口:通过在resources/METAINF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider文件中声明你的 SymbolProcessorProvider 实现类,KSP 编译器才能加载你的注解处理器。
class KotlinMvvmProcessorProvider : SymbolProcessorProvider {

    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
        return KotlinMvvmProcessor(environment.codeGenerator, environment.logger)
    }
}

✅ SymbolProcessor 的作用

  • 扫描注解
  • 生成代码
  • 提供编译时信息
  • 支持 Kotlin DSL、KAPT 替代方案:是 KAPT 的轻量级替代方案,更适合 Kotlin 项目,性能更优。
    核心方法process
class KotlinMvvmProcessor(
    codeGenerator: CodeGenerator,
    private val logger: KSPLogger
) : SymbolProcessor {
    companion object {
        private const val TAG = "KotlinMvvmProcessor"

    }

    private val serviceApiGenerator = ServiceApiGenerator(codeGenerator, logger)
    private val prefsGenerator = PrefsGenerator(codeGenerator, logger)
    private val kotlinMvvmGenerator = KotlinMvvmGenerator(codeGenerator, logger)
    private val activityGenerator = ActivityGenerator(codeGenerator, logger)
	// 每次 KSP 执行注解处理时都会调用它
    override fun process(resolver: Resolver): List<KSAnnotated> {
        kotlinMvvmGenerator.process(resolver)
        serviceApiGenerator.process(resolver)
        prefsGenerator.process(resolver)
        activityGenerator.process(resolver)
        return emptyList()
    }
}

1.3 ActivityGenerator例子

在 Kotlin 编译阶段,根据开发者在 Activity 类上添加的 @Title 和 @StatusBar 注解,自动生成标题栏和状态栏的配置与初始化代码,简化 BaseActivity 的通用 UI 配置逻辑。

  • 部分核心代码举例
/**
 * 在 Kotlin 编译阶段(KSP),扫描项目中所有被指定注解(T)修饰的类声明(KSClassDeclaration),并返回这些类的列表。
 * Resolver接口类:Kotlin KSP 提供的接口,用于访问编译期的符号信息。
 */
inline fun <reified T> Resolver.getKSClassDeclarations(): List<KSClassDeclaration> {
    return getSymbolsWithAnnotation(T::class.qualifiedName!!)
        .filterIsInstance<KSClassDeclaration>().toList()
}
    /**
     * 遍历所有被 @Title 或 @StatusBar 注解修饰的 Activity 类,
     * 并为每个类生成一个对应的 XXX_Compiler 类,用于运行时注入标题栏和状态栏的配置与初始化逻辑。
     */
    private fun generate(list: Set<KSClassDeclaration>) {
        list.forEach {
            val title = it.getAnnotation<Title>()

            val statusBar = it.getAnnotation<StatusBar>()

            val className = it.toClassName().simpleName
            val fullPackageName = it.toClassName().packageName

            val typeSpecBuilder = TypeSpec
                .classBuilder("${className}_Compiler")
                .addModifiers(KModifier.FINAL, KModifier.PUBLIC)
                .addSuperinterface(CLASS_NAME_ACTIVITY_COMPILER)
                .addProperty(initTitleProperty(title, className))
                .addProperty(initStatusBarProperty(statusBar, className))
            val funSpec = initTitleMenuOnClick(it, title)
            funSpec?.let { fsc ->
                typeSpecBuilder.addFunction(fsc)
            }
            typeSpecBuilder.addFunction(injectFun(className, funSpec != null))

            val typeSpec = typeSpecBuilder.build()
            // 将构建好的类 TypeSpec 转换为 .kt 文件;
            // 使用 FileSpec.builder 构建文件结构
            // 添加包名、类定义、导入 R 资源类
            // 使用 codeGenerator 写入到编译器生成的源码目录中
            FileSpec
                .builder(fullPackageName, typeSpec.name!!)
                .addType(typeSpec)
                .addImport("com.catchpig.mvvm", "R")
                .build()
                .writeTo(codeGenerator, false)
        }
    }
  • 关键FileSpec 类
    FileSpec 是 KotlinPoet 库中的一个核心类,用于构建 Kotlin 源代码文件(.kt 文件)的抽象表示。它是 KotlinPoet 提供的 API 中用于生成 Kotlin 文件结构的主要方式。
val fileSpec = FileSpec.builder("com.example.demo", "HelloWorld")
    .addImport("kotlin.io", "println")
    .addType(
        TypeSpec.classBuilder("Greeter")
            .addFunction(
                FunSpec.funBuilder("greet")
                    .addStatement("println(\"Hello, world!\")")
                    .build()
            )
            .build()
    )
    .build()

// 输出:

package com.example.demo

import kotlin.io.println

class Greeter {
    fun greet() {
        println("Hello, world!")
    }
}

1.4 在Activity中应用

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class StatusBar(
        /**
         * 隐藏状态栏
         */
        val hide: Boolean = false,
        /**
         * 状态栏注解是否可用<br/>
         * true:可用<br/>
         * false:不可用<br/>
         */
        val enabled: Boolean = true,
        /**
         * 状态栏透明
         */
        val transparent: Boolean = false
)
@StatusBar(transparent = true)
class MainActivity : BaseVMActivity<ActivityMainBinding, MainViewModel>(),
    ViewPager.OnPageChangeListener {
    }

2. 简介

KSP(Kotlin Symbol Processing) 是由 JetBrains 和 Google 推出的一种 Kotlin 编译期注解处理框架,用于替代传统的 KAPT(Kotlin Annotation Processing Tool)。它提供了一种轻量级、快速、类型安全的方式来处理 Kotlin 源代码中的注解,并生成相应的代码。

2.1 KSP 的核心作用

在 Kotlin 编译阶段分析源码中的注解信息,并生成对应的代码,用于实现诸如依赖注入、路由跳转、数据绑定等功能。

2.2 KSP 的核心组件

在这里插入图片描述

2.3 KSP 的处理流程

  • 扫描注解:通过 Resolver 扫描所有被指定注解修饰的类、方法、属性等。
  • 分析注解信息:提取注解参数,如 @Title(value = “首页”) 中的 value 值。
  • 生成代码:使用 CodeGenerator 和 KotlinPoet 生成 Kotlin 源码文件。
  • 注入代码:生成的代码在运行时被调用,完成特定逻辑(如依赖注入、UI 初始化等)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值