带有匕首 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
}

预期结果

接口TestCTestA注入在MainActivity

接口TestBTestA被注入到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

我找到的解决方案如下:

  • 创建一个对象,我可以在其中实例化将与 InjectorTestCImplementation

    共享的 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

的相同实例