在Kotlin的Injekt库中,如何为每个Android活动创建本地范围?
在Github上的Injekt文档中,它说范围是存在的,但我不清楚如何使用它们为每个Android活动创建一个本地范围,它们有自己的工厂和实例,但也可以使用父范围中的某些范围。
Injekt
variables似乎是一个全局范围,我看到InjektScope
和InjektScopeMain
但没有使用它们的例子,或者它们如何链接到父范围。 我看到的唯一方法是创建单独的InjektScope
实例并调用它们,或者将Injekt
作为全局范围调用。 这工作,但笨拙。
没有明显的方式来链接,嵌套,委托或inheritance。
这是支持的,如果是的话如何?
注意: 这个问题是由作者故意编写和回答的( 自我回答问题 ),所以对于常见的Injekt + Kotlin主题的习惯性的回答在SO中出现。 其他答案也欢迎,还有其他样式的如何做到这一点! 披露,我是Injekt图书馆的作者。
更新: 这现在记录在Injekt自述文件中
它由范围之间的工厂委托支持。 首先,一些背景:
Injekt允许将实例手动范围化为单独的Injektregistry。 通过Injekt
variables可用的全局registry只是为您预先创建的一个范围。 你也可以创建新的:
val myLocalScope: InjektScope = InjektScope(DefaultRegistrar())
这使得一个独立的范围与全球或其他人没有任何关系。
但是,您可以通过在新范围中创建工厂来将范围委派给另一个范围,从而链接范围。 例如, myLocalScope
提到的myLocalScope
可以将一些工厂委托给Injekt
全局范围:
// delegate some factories to global Injekt instance myLocalScope.addSingletonFactory { Injekt.get() } myLocalScope.addFactory { Injekt.get() }
当委派这样的工厂时,任何多值实例都不会被任何范围缓存,因为这些工厂在每次调用时都会创建新的实例。 对于单例和键控工厂,对象被缓存,并且对于在其生命周期中请求的任何实例,对这些对象的引用将存在于本地和委托范围中。
您也可以独立使用多个范围,而无需链接或委派。 从本地范围获取一些实例,从全局范围获取其他实例。 但是您必须独立使用每个范围,并且在意图不小心使用Injekt
全局variables时要小心。
如果您在本地范围内需要共同的工厂,则可以轻松创建InjektScope
的后代, 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() } } } // 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
相同的模型创建InjektMain
的后代,覆盖函数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() } } } // then in each place you want a local scope val localScope = MyActivityModule().scope
而且您仍然可以使用委托属性,只要在代理中使用之前声明范围即可:
val myProp: SomeClass by localScope.injectValue()
您可以使用LocalScoped
基类来使injectValue()
和injectLazy()
本地版本在注入成员时更加方便(请参阅LocalScoped
代码 )。 这样你的语法保持一致(参见测试示例 )。
要清除本地范围,请删除对范围的引用,然后将garabage收集起来。 没有明确的方法。
对于更高级的,更自动的范围链接/委托/inheritance,请参阅Injekt Github Issue#31,并提供关于这个可能的未来function的评论。
对于其他类在注入声明本地作用域的类中inheritance其相同本地作用域的用例,请参见Injekt Github Issue#32