2016-02-10 56 views
2

在Github上的Injekt文檔中,它說範圍存在,但我不清楚如何使用它們爲每個Android活動創建一個本地範圍,它們有自己的工廠和實例,但也可以使用父類中的一些範圍。在Kotlin的Injekt庫中,如何爲每個Android活動創建本地範圍?

Injekt變量似乎是一個全局範圍,我看到InjektScopeInjektScopeMain但沒有關於如何使用它們或者它們如何鏈接到父範圍的示例。我看到的唯一方法是創建單獨的InjektScope實例並調用它們,或者將Injekt作爲全局範圍。這工作,但笨拙。

沒有明顯的方式來鏈接,嵌套,委託或繼承。

這是否支持,如果有,如何?

注:這個問題是故意寫的,並回答了作者(Self-Answered Questions),從而使慣用解答常見Injekt +科特林主題存在於SO。其他答案也歡迎,還有其他樣式的如何做到這一點!披露,我是Injekt圖書館的作者。

回答

4

UPDATE:現在這是記錄在Injekt README

它支持範圍之間的委託工廠。首先,一些背景:

Injekt允許將實例手動範圍化爲單獨的Injekt註冊表。通過Injekt變量提供的全局註冊表只是爲您預先創建的一個範圍。您還可以創建新的:

val myLocalScope: InjektScope = InjektScope(DefaultRegistrar()) 

這使得具有全球或其他人沒有關係的獨立範圍。

但是,您可以通過在新範圍中創建工廠來將範圍委託給另一個範圍,從而鏈接範圍。例如上面提到的myLocalScope可以委託一些工廠,以Injekt全球範圍內:

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

當委託工廠,如此,任何多的值時,將不會被任何範圍,因爲這些工廠在創建新實例緩存每個電話。對於單件和鍵控工廠,對象將被緩存,並且對於在其生命週期中請求的任何實例,對這些對象的引用將存在於本地和委託範圍中。

您也可以獨立使用多個範圍,而無需鏈接或委派。從本地範圍獲取一些實例,從全局範圍獲取其他實例。但是您必須獨立使用每個範圍,並且在意圖不小心使用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 

,你仍然可以使用委託的屬性,只要範圍在委託使用前宣佈:

val myProp: SomeClass by localScope.injectValue() 

可以使用LocalScoped基類有本地版本injectValue()injectLazy(),以便在注射成員時更方便(請參閱code for LocalScoped)。這樣你的語法保持一致(見example in tests)。

要清除本地範圍,請刪除對範圍的引用,並將garabage收集起來。沒有明確的明確方法。

如需更先進,更自動的作用域鏈接/授權/繼承,請參閱Injekt Github Issue #31並提供有關此可能的未來功能的評論。

對於具有其他類的用例繼承相同的局部範圍內,當它們被注入類聲明的局部範圍內,看到Injekt Github Issue #32

+0

注:'LocalScoped'和測試例子是在即將到來的版本'1.13。 0「,儘管它們的等效代碼可以在當前版本中使用。 '1.3.0-RC-1050'可以在bintray repo'http:// dl.bintray.com/jaysonminard/kohesive'上找到,並且需要Kotlin EAP RC 1050. Maven Central的發佈將會發生,因爲RC不再是EAP 。 –

相關問題