Проблема с введением в действие подкомпонента кинжала
Мне трудно понять, как настроить иерархию компонентов Dagger в соответствии с моим видением. Любая помощь будет принята с благодарностью, и, пожалуйста, не стесняйтесь критиковать это видение, если вы обнаружите в нем какие-либо дыры.
Давайте перейдем к делу.
Я пытаюсь пересмотреть часть моего приложения, связанного с регистрацией пользователей. Поскольку регистрация является автономным доменом, я предполагаю, что это хороший кандидат для отдельного компонента кинжала (RegistrationSubcomponent). В этом домене регистрации я покажу активность (RegistrationActivity) и поверх нее несколько фрагментов (RegistrationFragment1, RegistrationFragment2, ...). У меня уже есть компонент приложения (AppComponent) с жизненным объемом приложения, который должен быть родительским для RegistrationSubcomponent. AppComponent используется для внедрения зависимостей в другие активности, кроме RegistrationActivity, но также и в общую активность (CommonActivity), которая является родительской для каждой активности в моем приложении, включая RegistrationActivity. Чтобы ввести зависимости в RegistrationActivity, я хочу использовать RegistrationSubcomponent.
Компонент RegistrationSubponent должен быть создан незадолго до отображения RegistrationActivity и должен существовать до возвращения RegistrationActivity. Я не хочу связывать жизненный цикл RegistrationSubcomponent с жизненным циклом RegistrationActivity. Mayby в этом случае может иметь смысл, но в будущем я, вероятно, хотел бы создать компоненты для других доменов приложений, которые могут не соответствовать жизненному циклу действий, которые они охватывают.
В общем, проблема заключается во внедрении зависимостей, указанных в RegistrationComponent, в RegistrationActivity, а также в RegistrationFragments.
Проблема заключается в том, что приложение аварийно завершает работу при переходе к RegistrationActivity со следующей ошибкой: невозможно запустить действие ComponentInfo{pl.kermit.diproblem/pl.kermit.diproblem.activities.RegistrationActivity}: java.lang.IllegalArgumentException: фабрика инжектора не привязана для класса
Минимальный проект, представляющий проблему, может быть найден в https://github.com/mariola3000/DIProblemStack01
Ниже я поместил наиболее важные части кода
// APP КОМПОНЕНТ
@Singleton
@Component(modules = [AndroidInjectionModule::class, AppModule::class, AppAndroidBindingModule::class,
AndroidSupportInjectionModule::class])
interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
fun inject(application: Application)
}
@Module(subcomponents = [RegistrationComponent::class])
class AppModule {
@Provides
fun provideGlobalDependency(): GlobalDependency {
return GlobalDependency("GlobalDependency")
}
@Provides
fun provideGlobal2Dependency(): Global2Dependency {
return Global2Dependency("Global2Dependency")
}
}
@Module
abstract class AppAndroidBindingModule {
@PerActivity
@ContributesAndroidInjector()
abstract fun bindMainActivity(): MainActivity
}
// РЕГИСТРАЦИОННЫЙ КОМПОНЕНТ
@PerRegistration
@Subcomponent(modules = [RegistrationModule::class, RegistrationAndroidBindingModule::class])
interface RegistrationComponent {
@Subcomponent.Builder
interface Builder {
fun requestModule(module: RegistrationModule): Builder
fun build(): RegistrationComponent
}
}
@Module
class RegistrationModule {
@PerRegistration
@Provides
fun provideRegistrationDependency(): RegistrationDependency {
return RegistrationDependency("RegistrationDependency")
}
@PerRegistration
@Provides
fun provideRegistrationFragmentDependency(): RegistrationFragmentDependency {
return RegistrationFragmentDependency("RegistrationFragmentDependency")
}
}
@Module
abstract class RegistrationAndroidBindingModule {
@PerActivity
@ContributesAndroidInjector
abstract fun bindRegistrationActivity(): RegistrationActivity
@PerFragment
@ContributesAndroidInjector
abstract fun bindRegistrationFragment(): RegistrationFragment
}
// ДЕЯТЕЛЬНОСТЬ
abstract class CommonActivity : DaggerAppCompatActivity(){
@Inject
lateinit var globalDependency: GlobalDependency
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
Toast.makeText(this, "global message: " + globalDependency.message, Toast.LENGTH_LONG).show()
}
}
class MainActivity : CommonActivity() {
@set:Inject
lateinit var global2Dependency: Global2Dependency
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val text: TextView = findViewById(R.id.main_text)
text.text = global2Dependency.message
val button: Button = findViewById(R.id.main_button)
button.setOnClickListener {
startActivity(Intent(this, RegistrationActivity::class.java))
}
}
}
class RegistrationActivity : CommonActivity() {
@Inject
lateinit var registrationDependency: RegistrationDependency
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_registration)
val registrationMessage = findViewById<TextView>(R.id.registration_text)
registrationMessage.text = registrationDependency.message
val transaction = this.supportFragmentManager.beginTransaction()
val fragment = RegistrationFragment()
transaction.replace(R.id.registration_fragment_container, fragment)
transaction.addToBackStack(fragment.javaClass.simpleName)
transaction.commit()
}
}