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

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

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

没有明显的方式来链接,嵌套,委托或inheritance。

这是支持的,如果是的话如何?

注意: 这个问题是由作者故意编写和回答的( 自我回答问题 ),所以对于常见的Injekt + Kotlin主题的习惯性的回答在SO中出现。 其他答案也欢迎,还有其他样式的如何做到这一点! 披露,我是Injekt图书馆的作者。

更新: 这现在记录在Injekt自述文件中

它由范围之间的工厂委托支持。 首先,一些背景:

Injekt允许将实例手动范围化为单独的Injektregistry。 通过Injektvariables可用的全局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