Проблема с введением в действие подкомпонента кинжала - PullRequest
0 голосов
/ 13 декабря 2018

Мне трудно понять, как настроить иерархию компонентов 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()
    }
}
...