带有匕首 2 的不同范围的单个实例
Single instance for different scopes with dagger 2
问题
我正在构建一个具有动态功能的应用程序。
为了提供对主模块和功能模块的所有依赖,我使用了 dagger 2。功能组件依赖于主要组件,因此,功能组件与主要组件具有不同的范围范围(@Singleton
在这种情况下)
在主模块中注入的接口之一是在功能模块上实现的,并在主模块中通过反射提供。该实现也用于功能模块。
我遇到的问题是主模块中提供的实例与功能模块中的实例不同(因为作用域),但我希望 dagger 只提供一个实例。
代码
这里有一些代码,您可以在 github
中找到整个示例项目
主模块的 Dagger 配置:
TestModule.kt
@Module
class TestModule {
@Provides
@Singleton
fun provideTestA() : TestA = TestAImplementation()
private var testCProvider: TestC?= null
@Provides
@Singleton
fun provideTestC(testComponent: TestComponent) : TestC {
if(testCProvider != null) return testCProvider as TestC
val provider = Class.forName("com.example.feature.services.TestCImplementation$Provider").kotlin.objectInstance as TestC.Provider
return provider
.get(testComponent)
.also { testCProvider = it }
}
}
TestComponent.kt
@Singleton
@Component(modules = [TestModule::class])
interface TestComponent {
fun inject(activity: MainActivity)
fun provideTestA() : TestA
}
功能模块的 Dagger 配置:
TestDependencyModule.kt
@Module
class TestDependencyModule {
@Provides
@TestScope
fun provideTestB(): TestB = TestBImplementation()
@Provides
@TestScope
fun provideTestC(testB: TestB): TestC = TestCImplementation(testB)
}
TestDependencyComponent.kt
@TestScope
@Component(
modules = [TestDependencyModule::class],
dependencies = [TestComponent::class]
)
interface TestDependencyComponent {
fun inject(receiver: TestBroadcastReceiver)
fun testC(): TestC
}
预期结果
接口TestC
和TestA
注入在MainActivity
接口TestB
和TestA
被注入到TestBroadcastReceiver
正如预期的那样,TestA
实现的实例是唯一的,但 TestB
的实现并非如此。由于 TestC
依赖于 TestB
,因此在 TestC
中注入的与在 TestBroadcastReceiver
中注入的不同,带有 @TestScope
注释。
因此 运行 您可以找到的示例项目 here 我得到以下日志输出
在 MainActivity
中注入的实例
D/TestB: instance 40525431
D/TestC: instance 119319268
D/TestA: instance 60713805
在 TestBroadcastReceiver
中注入的实例
D/TestB: instance 219966227
D/TestA: instance 60713805
我想在两个模块中共享相同的 TestB
实例。
有什么建议吗?
提前致谢!
TestDependencyComponent 无法从 TestComponent 上的组件依赖项访问 TestC,因为 TestComponent 未在其 public API 上公开 TestC。如果您在 TestComponent 上添加 fun testC(): TestC
,我希望您在处理 TestDependencyComponent 时会收到重复绑定异常。从那里您需要确定提供 TestC 实例的正确方法。
我正在构建 DaggerTestDependencyComponent
的两个实例,一个在 Injector
中,另一个在您实施时 TestC
我找到的解决方案如下:
创建一个对象,我可以在其中实例化将与 Injector
和 TestCImplementation
共享的 TestDependencyComponent
object FeatureInjector {
val testDependencyComponent: TestDependencyComponent by lazy {
DaggerTestDependencyComponent.builder()
.testComponent(com.example.daggertest.dagger.Injector.testComponent)
.build()
}
}
现在我修改了我的特征Injector
:
object Injector {
lateinit var testDependencyComponent: TestDependencyComponent
@JvmStatic
internal fun getTestDependencyComponent(): TestDependencyComponent {
if (!::testDependencyComponent.isInitialized) {
testDependencyComponent = FeatureInjector.testDependencyComponent
}
return testDependencyComponent
}
}
而TestCImplementation
如下:
class TestCImplementation @Inject constructor(
private val testB: TestB
) : TestC {
override fun testCFun() {
testB.testBFun()
Log.d("TestC", "instance ${System.identityHashCode(this)}")
}
companion object Provider : TestC.Provider {
override fun get(testComponent: TestComponent): TestC {
return FeatureInjector.testDependencyComponent.testC()
}
}
}
运行 代码现在我得到了 TestB
的相同实例
问题
我正在构建一个具有动态功能的应用程序。
为了提供对主模块和功能模块的所有依赖,我使用了 dagger 2。功能组件依赖于主要组件,因此,功能组件与主要组件具有不同的范围范围(@Singleton
在这种情况下)
在主模块中注入的接口之一是在功能模块上实现的,并在主模块中通过反射提供。该实现也用于功能模块。
我遇到的问题是主模块中提供的实例与功能模块中的实例不同(因为作用域),但我希望 dagger 只提供一个实例。
代码
这里有一些代码,您可以在 github
中找到整个示例项目主模块的 Dagger 配置:
TestModule.kt
@Module
class TestModule {
@Provides
@Singleton
fun provideTestA() : TestA = TestAImplementation()
private var testCProvider: TestC?= null
@Provides
@Singleton
fun provideTestC(testComponent: TestComponent) : TestC {
if(testCProvider != null) return testCProvider as TestC
val provider = Class.forName("com.example.feature.services.TestCImplementation$Provider").kotlin.objectInstance as TestC.Provider
return provider
.get(testComponent)
.also { testCProvider = it }
}
}
TestComponent.kt
@Singleton
@Component(modules = [TestModule::class])
interface TestComponent {
fun inject(activity: MainActivity)
fun provideTestA() : TestA
}
功能模块的 Dagger 配置:
TestDependencyModule.kt
@Module
class TestDependencyModule {
@Provides
@TestScope
fun provideTestB(): TestB = TestBImplementation()
@Provides
@TestScope
fun provideTestC(testB: TestB): TestC = TestCImplementation(testB)
}
TestDependencyComponent.kt
@TestScope
@Component(
modules = [TestDependencyModule::class],
dependencies = [TestComponent::class]
)
interface TestDependencyComponent {
fun inject(receiver: TestBroadcastReceiver)
fun testC(): TestC
}
预期结果
接口TestC
和TestA
注入在MainActivity
接口TestB
和TestA
被注入到TestBroadcastReceiver
正如预期的那样,TestA
实现的实例是唯一的,但 TestB
的实现并非如此。由于 TestC
依赖于 TestB
,因此在 TestC
中注入的与在 TestBroadcastReceiver
中注入的不同,带有 @TestScope
注释。
因此 运行 您可以找到的示例项目 here 我得到以下日志输出
在 MainActivity
D/TestB: instance 40525431
D/TestC: instance 119319268
D/TestA: instance 60713805
在 TestBroadcastReceiver
D/TestB: instance 219966227
D/TestA: instance 60713805
我想在两个模块中共享相同的 TestB
实例。
有什么建议吗? 提前致谢!
TestDependencyComponent 无法从 TestComponent 上的组件依赖项访问 TestC,因为 TestComponent 未在其 public API 上公开 TestC。如果您在 TestComponent 上添加 fun testC(): TestC
,我希望您在处理 TestDependencyComponent 时会收到重复绑定异常。从那里您需要确定提供 TestC 实例的正确方法。
我正在构建 DaggerTestDependencyComponent
的两个实例,一个在 Injector
中,另一个在您实施时 TestC
我找到的解决方案如下:
创建一个对象,我可以在其中实例化将与
共享的Injector
和TestCImplementation
TestDependencyComponent
object FeatureInjector { val testDependencyComponent: TestDependencyComponent by lazy { DaggerTestDependencyComponent.builder() .testComponent(com.example.daggertest.dagger.Injector.testComponent) .build() } }
现在我修改了我的特征
Injector
:object Injector { lateinit var testDependencyComponent: TestDependencyComponent @JvmStatic internal fun getTestDependencyComponent(): TestDependencyComponent { if (!::testDependencyComponent.isInitialized) { testDependencyComponent = FeatureInjector.testDependencyComponent } return testDependencyComponent } }
而
TestCImplementation
如下:class TestCImplementation @Inject constructor( private val testB: TestB ) : TestC { override fun testCFun() { testB.testBFun() Log.d("TestC", "instance ${System.identityHashCode(this)}") } companion object Provider : TestC.Provider { override fun get(testComponent: TestComponent): TestC { return FeatureInjector.testDependencyComponent.testC() } } }
运行 代码现在我得到了 TestB