KSP初体验(二)

346 阅读2分钟

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

接上文我们完成了注解处理器的编写,还有个扫尾的工作需要完成。

注册注解处理器

我们需要在processor模块中注册我们的注解处理器。
创建文件processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider

文件内容为com.holderzone.store.processor.BuilderProcessorProvider,即SymbolProcessorProvider实现类的包名。

第三步创建XRouter模块

在模块的build.gradle.kts中加入以下代码:

plugins {
    id("com.android.library")
    id("org.jetbrains.kotlin.android")
}

android {
    compileSdk = 32

    defaultConfig {
        minSdk = 21
        targetSdk = 32
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.3.2")
    implementation("androidx.appcompat:appcompat:1.2.0")
    implementation("com.google.android.material:material:1.3.0")
    implementation("androidx.constraintlayout:constraintlayout:2.0.4")
    api(project(":annotation"))
}

由于使用到了Intent所以要使用com.android.library,另外注意这里使用的api来引入annotation依赖,这样app在使用XRouter时就不需要再次引入annotation模块了。

反射调用loadInfo

object XRouter {
    val hashMap = HashMap<String,Class<Any>>()

    var mContext:Context? = null

    fun init(context: Application){
        mContext = context
        val claName = "com.example.xrouter.XRouterPathCollector"
        val clazz = Class.forName(claName)
        val ob = clazz.newInstance()
        val collectMethod = clazz.getMethod("loadInfo", hashMap.javaClass)
        collectMethod.invoke(ob, hashMap)
    }

    public fun navigation(route:String) {
        if (mContext == null) return
        if (!hashMap.containsKey(route)) return;
        val intent = Intent(mContext, hashMap.get(route))
        intent.addFlags(FLAG_ACTIVITY_NEW_TASK)
        ActivityCompat.startActivity(mContext!!, intent,null )
    }

}

XRouter的实现很简单,在init时传入Application context,另外使用反射调用XRouterPathCollector的loadInfo方法,将路由信息加载到hashMap中。
当调用navigation方法时,去hashMap中找到对应的路由信息,构建Intent类,实现跳转。

使用

在app的build.gradle.kts中加入以下代码:


plugins {
    id ("com.android.application")
    id ("kotlin-android")
    id ("com.google.devtools.ksp") version ("1.5.31-1.0.0")
}

dependencies {
    ...
    ksp(project(":processor"))
    implementation(project(":xrouter"))
}

在Application进行初始化:

class App: Application() {
    override fun onCreate() {
        super.onCreate()
        XRouter.init(this)
    }
}

在对应Activity添加Route注解:


@Route(route = "Main")
class MainActivity : AppCompatActivity() {
  
}

@Route(route = "Second")
public class SecondActivity extends AppCompatActivity {
  
}

到这一步我们可以先重新编译一次代码,不出意外的话在app/build/generated/ksp/debug/kotlin/com/example/xrouter目录下会生成如下代码:


package com.example.xrouter

import android.app.Activity
import java.lang.Class
import java.util.HashMap
import kotlin.String
import kotlin.Unit

public class XRouterPathCollector {
  public fun loadInfo(map: HashMap<String, Class<out Activity>>): Unit {
    map["Main"] = com.holderzone.store.ksptest.MainActivity::class.java
    map["Second"] = com.holderzone.store.ksptest.SecondActivity::class.java
  }
}

如果没有生成,那就得好好看一下ksp的log,分析是哪步出错了。

想要跳转到第二个Activity时,只需要使用XRouter.navigation("Second")即可完成跳转。ok我们的XRouter写到这里就算完成了,当然有很多地方可以完善补充,例如KSP采用增量编译、添加传参跳转功能、将XRouter和processor发布到maven等等。

本文只是介绍了ksp是什么以及怎么用,没有过多的介绍它的API,它是可以拿到所有类、方法、属性的注解等信息的。更多细节及用法请参考官网