Единичный экземпляр для разных прицелов с кинжалом 2
Проблема
Я создаю приложение с динамической функцией.
Чтобы обеспечить все зависимости для основного модуля и функционального модуля, я использую кинжал 2. Компонент функции зависит от основного компонента, и из-за этого компонент функции имеет область, отличную от области действия основного компонента (@Singleton
в этом случае)
Один из интерфейсов, внедренных в основной модуль, реализован в функциональном модуле и обеспечивается отражением в основном модуле. Реализация также используется в функциональном модуле.
Проблема, с которой я столкнулся, заключается в том, что экземпляр, представленный в основном модуле, отличается от экземпляра в функциональном модуле (из-за возможностей), но я хотел бы иметь только один экземпляр с кинжалом.
Код
Вот код, и вы можете найти весь пример проекта в github
Конфигурация кинжала для основного модуля:
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
аннотация.
Итак, запустив пример проекта, который вы можете найти здесь, я получаю следующий вывод журнала
Экземпляры, введенные в MainActivity
D/TestB: instance 40525431
D/TestC: instance 119319268
D/TestA: instance 60713805
Экземпляры, введенные в TestBroadcastReceiver
D/TestB: instance 219966227
D/TestA: instance 60713805
Я хотел бы поделиться тем же экземпляром TestB
в обоих модулях.
Любое предложение? Заранее спасибо!
2 ответа
Я строил два экземпляра DaggerTestDependencyComponent
один в Injector
и еще один другой, когда вы реализуете TestC
Решение, которое я нашел, было следующее:
Создайте объект, в котором я могу создать экземпляр
TestDependencyComponent
это будет переданоInjector
иTestCImplementation
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
TestDependencyComponent не может получить доступ к TestC из зависимости компонента от TestComponent, поскольку TestComponent не предоставляет TestC в своем общедоступном API. Если вы добавитеfun testC(): TestC
on TestComponent, я ожидаю, что вы получите дублирующееся исключение привязки при обработке TestDependencyComponent. Оттуда вам нужно будет определить правильный способ предоставления экземпляра TestC.