我很难弄清楚如何设置Dagger组件层次结构以符合我的愿景。任何帮助将不胜感激,如果发现任何漏洞,请随时批评它。
我们要点了。
我正在尝试兑现与用户注册有关的部分应用程序。由于注册是一个自包含域,因此我认为它是单独的匕首组件(RegistrationSubcomponent)的不错的选择。在该注册域中,我将显示一个活动(RegistrationActivity),并在其顶部显示一些片段(RegistrationFragment1,RegistrationFragment2等)。我已经有一个应用程序组件(AppComponent),其应用程序的生命周期应为RegistrationSubcomponent的父级。 AppComponent用于将依赖项注入到除RegistrationActivity之外的其他活动中,也注入到一个公共活动(CommonActivity)中,该活动是我的应用程序中每个活动(包括RegistrationActivity)的父级。要将依赖项注入RegistrationActivity,我想使用RegistrationSubcomponent。
应该在显示RegistrationActivity之前立即实例化RegistrationSub组件,并且应该一直存在,直到RegistrationActivity返回。我不想将RegistrationSubcomponent生命周期与RegistrationActivity生命周期绑定。也许在这种情况下可能是有道理的,但将来我可能想为其他应用程序域创建可能不一定与它们包含的活动的生命周期相匹配的组件。
通常,问题是将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()
}
}