【问题标题】:Create function inheriting koin component创建继承koin组件的函数
【发布时间】:2019-10-08 14:01:57
【问题描述】:

我正在尝试简化:

// Tag class with KoinComponent
class HelloApp : KoinComponent {

    // lazy inject dependency
    val helloService: HelloServiceImpl by inject()

    fun sayHello(){
        helloService.sayHello()
    }
}

类似

fun sayHello() = koinComponent {
    val helloService: HelloServiceImpl by inject()
    helloService.sayHello()
}

这样有可能吗,或者我注定要使用invoke 运算符创建一个类?

【问题讨论】:

    标签: kotlin koin


    【解决方案1】:

    嗯,这是可行的:

    首先,让我们定义服务和实现:

    interface HelloService {
        fun sayHello()
    }
    
    class HelloServiceImpl(private val name: String) : HelloService {
        override fun sayHello() {
            println("Hello, $name!")
        }
    }
    

    很明显,服务会向在其构造函数中配置的人说“Hello”。

    现在,koinComponent 函数:

    fun <T> koinComponent(block: Koin.() -> T) {
        GlobalContext.get().koin.block()
    }
    

    你的功能:

    fun sayHello() = koinComponent {
        val helloService: HelloServiceImpl by inject()
    
        helloService.sayHello()
    }
    

    及用法:

    fun main() {
        startKoin {
            modules(listOf(
                module {
                    single { HelloServiceImpl("majkrzak") }
                }
            ))
        }
    
        sayHello()
    }
    

    输出:Hello, majkrzak!

    这一切都非常简单:为了能够使用inject delegate,您需要一个 Koin 上下文。实际上,KoinComponent 的工作方式是使用GlobalContext

    interface KoinComponent {
        fun getKoin(): Koin = GlobalContext.get().koin
    }
    
    inline fun <reified T> KoinComponent.inject(
            qualifier: Qualifier? = null,
            noinline parameters: ParametersDefinition? = null
    ): Lazy<T> =
            getKoin().inject(qualifier, parameters)
    

    那么,为什么不这样做呢?我们声明了koinComponent 函数,以便它的block 参数被Koin 接收器调用并隐式使用该全局koin 实例。

    我们可以通过使用默认值使其更具可重用性:

    fun <T> koinComponent(koin: Koin = GlobalContext.get().koin, block: Koin.() -> T) {
        koin.block()
    }
    

    现在我有一个问题要问你:你为什么需要它?

    【讨论】:

    • 主要是在使用 Kotllin 进行试验。目前我已经实现了简单的服务形式:class Query : KoinComponent { private val client: HttpClient by inject() suspend operator fun invoke(query: String) = client.post&lt;Response&gt;(url) { body = query } } 并且想知道我是否可以更简化一点。
    • 我刚刚意识到这是一种解决方法,有什么合法的方法吗?
    • 这段代码有什么问题?它完全KoinComponent一样工作。
    猜你喜欢
    • 1970-01-01
    • 2015-02-01
    • 2017-11-01
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多