KRouter 在前几天发布的新版 1.2.1 已经支持了 Kotlin Multiplatform SPI 机制,基于 KSP 和注解。
SPI 机制
首先介绍一下 SPI 到底是什么。SPI 全称 Service Provider Interface,也被称为服务发现,在 Java 中通过 ServiceLoader 来实现。实际上是指在运行时获取一个接口所有的实现类。
如果我们某种服务通过一个接口描述,并且在源码结构上无法获取到接口所有的实现类,比如实现类分散在各个模块,甚至是运行时加载的模块,那么我们就可以通过 SPI 在运行时获取到这个接口所有的实现类。
interface HtmlParser {
fun parse(document: String): String
}
// Module A
class Html1Parser : HtmlParser {
override fun parse(document: String): String {
return document
}
}
// Module B
class Html2Parser : HtmlParser {
override fun parse(document: String): String {
return document
}
}
// Application
fun main() {
val parsers = ServiceLoader.load(HtmlParser::class.java, HtmlParser::class.java.classLoader)
}
如上,这样就是一个简单的 SPI 实现。
Kotlin SPI
上述方式是通过 Java 的能力做到的,Kotlin Multiplatform 本身没有提供这样的能力,因此只能自己想办法了。
好在 KRouter 天然具备通过注解收集信息的能力,只要稍加改造即可支持。
首先在使用上,KRouter 提供了一个 @Service 注解用于表示一个实现类,然后在编译的时候 KRouter 会自动收集类信息,这样就可以在运行时获取到所有的实现了。
interface HtmlParser {
fun parse(document: String): String
}
// Module A
@Service
class Html1Parser : HtmlParser {
override fun parse(document: String): String {
return document
}
}
// Module B
@Service(HtmlParser::class)
class Html2Parser : HtmlParser {
override fun parse(document: String): String {
return document
}
}
// Application
fun main() {
val parsers = KRouter.getServices<HtmlParser>()
}
就是这么简单,关于 KRouter 更多的使用请看上一篇文章。