给定BaseFragment及其子类: DerivedFragmentA,DerivedFragmentB,.
比方说,大多数@Inject字段对于每个片段都是通用的,因此在BaseFragment中声明:
abstract class BaseFragment : DaggerFragment() {
@Inject lateinit var vmFactory: ViewModelProvider.Factory
}
class DerivedFragmentA : BaseFragment()
class DerivedFragmentB : BaseFragment()
...对于每个派生片段,我们必须手动创建模块组件对,例如:
@Subcomponent
interface DerivedFragmentAComponent : AndroidInjector<DerivedFragmentA> {
@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<DerivedFragmentA>()
}
@Module(subcomponents = [DerivedFragmentAComponent::class])
abstract class DerivedFragmentAModule {
@Binds @IntoMap @FragmentKey(DerivedFragmentA::class)
abstract fun bind(builder: DerivedFragmentAComponent.Builder): AndroidInjector.Factory<out Fragment>
}并将每个组件安装到某个外部组件上,如下所示:
@Subcomponent(modules = [DerivedFragmentAModule::class, DerivedFragmentBModule::class, ...])
interface MainComponent : AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<MainActivity>()
}但这有点像样板。
如果我们只尝试为BaseFragment创建一个模块组件,并且只将它安装到MainComponent中,那么我们将在调用AndroidInjector.inject(fragment)方法期间获得一个运行时异常,其中包含以下消息:
"No injector factory bound for Class<DerivedFragmentA>. Injector factories were bound for supertypes of DerivedFragmentA: BaseFragment. Did you mean to bind an injector factory for the subtype?"有办法解决这个问题并避免代码重复吗?还是因为Dagger-2强烈依赖于类名,它的不可能?
发布于 2018-03-07 20:50:25
Dagger 2的注入总是适用于您指定的类型。inject(fragment : BaseFragment)只会注入BaseFragment字段,任何子类中都不会声明字段。这是你必须记住的事情。
您说您只想声明一个组件并将其注入到BaseFragment中,所以这正是您所能做的。不是为您的DerivedFragment创建一个子组件,而是为您的BaseFragment创建一个.
@Subcomponent
interface BaseFragmentComponent : AndroidInjector<BaseFragment> {
@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<BaseFragment>()
}然后,您可以将BaseFragment.Builder绑定到您的DerivedFragmentX。
@Module(subcomponents = [BaseFragmentComponent::class])
abstract class BaseFragmentModule {
@Binds @IntoMap @FragmentKey(DerivedFragmentA::class)
abstract fun bind(builder: BaseFragmentComponent.Builder): AndroidInjector.Factory<out Fragment>
@Binds @IntoMap @FragmentKey(DerivedFragmentB::class)
abstract fun bind(builder: BaseFragmentComponent.Builder): AndroidInjector.Factory<out Fragment>
@Binds @IntoMap @FragmentKey(DerivedFragmentC::class)
abstract fun bind(builder: BaseFragmentComponent.Builder): AndroidInjector.Factory<out Fragment>
}重要的一点是将@FragmentKey(DerivedFragmentA::class)设置为引用子类,因为这是Dagger在调用AndroidInjection.inject(fragment)时将查找的一个子类。
我仍然建议您不要使用这种方法,因为最终会有一些片段被完全注入,而另一些片段只是BaseFragment。这听起来让我很困惑。
您可以使用@ContributesAndroidInjector来为您生成样板代码,并正确地注入每个片段。
https://stackoverflow.com/questions/49153037
复制相似问题