带注解的定义
Koin 注解允许你声明与常规 Koin DSL 相同类型的定义,但通过注解完成。只需为你的类添加所需的注解标签,它就会为你生成所有内容!
例如,等同于 single { MyComponent(get()) }
DSL 声明,只需像这样添加 @Single
标签即可:
@Single
class MyComponent(val myDependency : MyDependency)
Koin 注解与 Koin DSL 保持相同的语义。你可以使用以下定义声明你的组件:
@Single
- 单例实例(在 DSL 中使用single { }
声明)@Factory
- 工厂实例。每次需要实例时都会重新创建的实例。(在 DSL 中使用factory { }
声明)@KoinViewModel
- Android ViewModel 实例(在 DSL 中使用viewModel { }
声明)@KoinWorker
- Android Worker Workmanager 实例(在 DSL 中使用worker { }
声明)
关于作用域,请查看 声明作用域 小节。
为 Kotlin Multipaltform 生成 Compose ViewModel (从 1.4.0 版本开始)
@KoinViewModel
注解可用于生成 Android 或 Compose KMP ViewModel。要使用 org.koin.compose.viewmodel.dsl.viewModel
而不是常规的 org.koin.androidx.viewmodel.dsl.viewModel
来生成 viewModel
Koin 定义,你需要激活 KOIN_USE_COMPOSE_VIEWMODEL
选项:
ksp {
arg("KOIN_USE_COMPOSE_VIEWMODEL","true")
}
NOTE
`USE_COMPOSE_VIEWMODEL` 键已弃用,请使用 `KOIN_USE_COMPOSE_VIEWMODEL`。
NOTE
Koin 4.0 应该会将这两个 ViewModel DSL 合并为一个,因为 ViewModel 类型参数来自同一个库。
自动绑定或特定绑定
声明组件时,所有检测到的“绑定”(关联的超类型)都将为你准备好。例如,以下定义:
@Single
class MyComponent(val myDependency : MyDependency) : MyInterface
Koin 将声明你的 MyComponent
组件也绑定到 MyInterface
。等同的 DSL 是 single { MyComponent(get()) } bind MyInterface::class
。
除了让 Koin 自动检测外,你还可以使用 binds
注解参数指定你真正想要绑定的类型:
@Single(binds = [MyBoundType::class])
可空依赖
如果你的组件使用了可空依赖,不用担心,它将自动为你处理。继续使用你的定义注解,Koin 将推断该怎么做:
@Single
class MyComponent(val myDependency : MyDependency?)
生成的 DSL 等价物将是 single { MyComponent(getOrNull()) }
请注意,这也适用于注入的参数和属性。
使用 @Named 的限定符
你可以为定义添加一个“名称”(也称为限定符),以使用 @Named
注解区分同一类型的多个定义:
@Single
@Named("InMemoryLogger")
class LoggerInMemoryDataSource : LoggerDataSource
@Single
@Named("DatabaseLogger")
class LoggerLocalDataSource(private val logDao: LogDao) : LoggerDataSource
解决依赖时,只需使用 named
函数配合限定符即可:
val logger: LoggerDataSource by inject(named("InMemoryLogger"))
也可以创建自定义限定符注解。使用之前的示例:
@Named
annotation class InMemoryLogger
@Named
annotation class DatabaseLogger
@Single
@InMemoryLogger
class LoggerInMemoryDataSource : LoggerDataSource
@Single
@DatabaseLogger
class LoggerLocalDataSource(private val logDao: LogDao) : LoggerDataSource
val logger: LoggerDataSource by inject(named<InMemoryLogger>())
使用 @InjectedParam 注入参数
你可以将构造函数成员标记为“注入参数”,这意味着在调用解析时,依赖项将被传递到图 (graph) 中。
例如:
@Single
class MyComponent(@InjectedParam val myDependency : MyDependency)
然后你可以调用你的 MyComponent
并传入 MyDependency
的实例:
val m = MyDependency
// Resolve MyComponent while passing MyDependency
koin.get<MyComponent> { parametersOf(m) }
生成的 DSL 等价物将是 single { params -> MyComponent(params.get()) }
注入懒加载依赖 - Lazy<T>
Koin 可以自动检测并解析懒加载依赖。例如,在这里我们想要懒加载地解析 LoggerDataSource
定义。你只需按如下方式使用 Kotlin Lazy
类型即可:
@Single
class LoggerInMemoryDataSource : LoggerDataSource
@Single
class LoggerAggregator(val lazyLogger : Lazy<LoggerDataSource>)
在底层,它会生成像使用 inject()
而不是 get()
的 DSL:
single { LoggerAggregator(inject()) }
注入依赖列表 - List<T>
Koin 可以自动检测并解析所有依赖列表。例如,在这里我们想要解析所有 LoggerDataSource
定义。你只需按如下方式使用 Kotlin List
类型即可:
@Single
@Named("InMemoryLogger")
class LoggerInMemoryDataSource : LoggerDataSource
@Single
@Named("DatabaseLogger")
class LoggerLocalDataSource(private val logDao: LogDao) : LoggerDataSource
@Single
class LoggerAggregator(val datasource : List<LoggerDataSource>)
在底层,它会生成像使用 getAll()
函数的 DSL:
single { LoggerAggregator(getAll()) }
使用 @Property 的属性
要在你的定义中解析 Koin 属性,只需将构造函数成员标记为 @Property
。这将通过传递给注解的值来解析 Koin 属性:
@Factory
public class ComponentWithProps(
@Property("id") public val id : String
)
生成的 DSL 等价物将是 factory { ComponentWithProps(getProperty("id")) }
@PropertyValue - 具有默认值的属性 (从 1.4 版本开始)
Koin 注解让你能够直接从你的代码中通过 @PropertyValue
注解为属性定义默认值。 让我们来看这个示例:
@Factory
public class ComponentWithProps(
@Property("id") public val id : String
){
public companion object {
@PropertyValue("id")
public const val DEFAULT_ID : String = "_empty_id"
}
}
生成的 DSL 等价物将是 factory { ComponentWithProps(getProperty("id", ComponentWithProps.DEFAAULT_ID)) }