gpt4 book ai didi

android - 在 Kotlin 的 Injekt 库中,如何为每个 Android Activity 创建本地范围?

转载 作者:搜寻专家 更新时间:2023-11-01 07:50:52 26 4
gpt4 key购买 nike

在 Github 上的 Injekt 文档中,它说范围存在,但不清楚我如何使用它们为每个 Android Activity 创建本地范围,这些 Activity 有自己的工厂和实例,但也可以使用来自父范围。

Injekt 变量似乎是一个全局范围,我看到了 InjektScopeInjektScopeMain 但没有关于如何使用它们的示例,或者它们如何链接到父范围。我看到的唯一方法是创建单独的 InjektScope 实例并调用它们,或者将 Injekt 作为全局范围调用。这可行,但很笨拙。

没有明显的链接、嵌套、委托(delegate)或继承方式。

这是否受支持,如果是如何支持?

注意: 这个问题是作者 ( Self-Answered Questions ) 有意编写和回答的,因此常见 Injekt + Kotlin 主题的惯用答案出现在 SO 中。也欢迎其他答案,还有其他样式的方法!披露,我是 Injekt 库的作者。

最佳答案

更新: 现在记录在 Injekt README

它由作用域之间的委托(delegate)工厂支持。首先,一些背景:

Injekt 允许手动将实例范围限定到单独的 Injekt 注册表中。通过 Injekt 变量可用的全局注册表只是为您预先创建的一个范围。您还可以创建新的:

val myLocalScope: InjektScope = InjektScope(DefaultRegistrar())

这形成了一个与全局或其他无关的独立范围。

但是您可以通过在新作用域中创建工厂将一些实例创建委托(delegate)给另一个作用域来链接作用域。例如上面提到的 myLocalScope 可以将一些工厂委托(delegate)给 Injekt 全局作用域:

// delegate some factories to global Injekt instance
myLocalScope.addSingletonFactory { Injekt.get<SomeSingletonClass>() }
myLocalScope.addFactory { Injekt.get<SomeMultiValueClass>() }

当像这样委托(delegate)工厂时,任何多值实例都不会被任何范围缓存,因为这些工厂在每次调用时都会创建新实例。对于单例和键控工厂,对象被缓存,并且对这些对象的引用将存在于本地和委托(delegate)范围内,用于在其生命周期内请求的任何实例。

您也可以独立使用多个作用域,而无需链接或委托(delegate)。从本地范围获取一些实例,从全局范围获取其他实例。但是您必须独立使用每个作用域,并小心不要意外使用了 Injekt 全局变量。

如果您在局部作用域中需要通用工厂,您可以轻松创建 InjektScope 的后代,在其构造期间注册这些工厂。

class MyActivityScope: InjektScope(DefaultRegistrar()) {
init {
// override with local value
addSingletonFactory { SomeSingletonClass() }
// import other registrations from defined modules
importModule(OtherModuleWithPrepackagedInjektions)
// delegate to global scope:
addSingletonFactory { Injekt.get<SomeOtherSingleton>() }
}
}

// then in each place you want a local scope
val localScope = MyActivityScope()

// later use the scope
val singly: SomeSingletonClass = localScope.get()
val other: SomeOtherSingleton = localScope.get()

或者使用与 InjektMain 相同的模型创建 InjektScopedMain 的后代,它覆盖函数 fun InjektRegistrar.registerInjectables() { ... } ,如果您希望与模块保持一致。例如:

class MyActivityModule: InjektScopedMain(InjektScope(DefaultRegistrar())) {
override fun InjektRegistrar.registerInjectables() {
// override with local value
addSingletonFactory { NotLazy("Freddy") }
// import other registrations from defined modules
importModule(OtherModuleWithPrepackagedInjektions)
// delegate to global scope:
addSingletonFactory { Injekt.get<SomeOtherSingleton>() }
}
}

// then in each place you want a local scope
val localScope = MyActivityModule().scope

并且您仍然可以使用委托(delegate)属性,只要在委托(delegate)中使用之前声明范围:

val myProp: SomeClass by localScope.injectValue()

你可以使用LocalScoped基类来拥有本地版本的injectValue()injectLazy(),让注入(inject)时更方便成员(见 code for LocalScoped )。这样您的语法就会保持一致(请参阅 example in tests )。

要清除本地作用域,请删除对该作用域的引用,它将垃圾收集掉。没有明确的清除方法。

有关更高级、更自动的作用域链接/委派/继承,请参阅Injekt Github Issue #31并就此可能的 future 功能发表评论。

有关在将其他类注入(inject)到声明局部范围的类中时让其他类继承相同局部范围的用例,请参阅 Injekt Github Issue #32

关于android - 在 Kotlin 的 Injekt 库中,如何为每个 Android Activity 创建本地范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35315548/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com