首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Dagger2:如何复制模块-组件forActivity /片段,依赖于单个基础(模块/组件)作为基础(活动/片段)&

Dagger2:如何复制模块-组件forActivity /片段,依赖于单个基础(模块/组件)作为基础(活动/片段)&
EN

Stack Overflow用户
提问于 2018-03-07 13:23:26
回答 1查看 785关注 0票数 3

给定BaseFragment及其子类: DerivedFragmentA,DerivedFragmentB,.

比方说,大多数@Inject字段对于每个片段都是通用的,因此在BaseFragment中声明:

代码语言:javascript
复制
abstract class BaseFragment : DaggerFragment() {
    @Inject lateinit var vmFactory: ViewModelProvider.Factory
}

class DerivedFragmentA : BaseFragment()
class DerivedFragmentB : BaseFragment()
...

对于每个派生片段,我们必须手动创建模块组件对,例如:

代码语言:javascript
复制
@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>
}

并将每个组件安装到某个外部组件上,如下所示:

代码语言:javascript
复制
@Subcomponent(modules = [DerivedFragmentAModule::class, DerivedFragmentBModule::class, ...])
interface MainComponent : AndroidInjector<MainActivity> {

    @Subcomponent.Builder
    abstract class Builder : AndroidInjector.Builder<MainActivity>()
}

但这有点像样板。

如果我们只尝试为BaseFragment创建一个模块组件,并且只将它安装到MainComponent中,那么我们将在调用AndroidInjector.inject(fragment)方法期间获得一个运行时异常,其中包含以下消息:

代码语言:javascript
复制
  "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强烈依赖于类名,它的不可能

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-07 20:50:25

Dagger 2的注入总是适用于您指定的类型。inject(fragment : BaseFragment)只会注入BaseFragment字段,任何子类中都不会声明字段。这是你必须记住的事情。

您说您只想声明一个组件并将其注入到BaseFragment中,所以这正是您所能做的。不是为您的DerivedFragment创建一个子组件,而是为您的BaseFragment创建一个.

代码语言:javascript
复制
@Subcomponent
interface BaseFragmentComponent : AndroidInjector<BaseFragment> {

    @Subcomponent.Builder
    abstract class Builder : AndroidInjector.Builder<BaseFragment>()
}

然后,您可以将BaseFragment.Builder绑定到您的DerivedFragmentX

代码语言:javascript
复制
@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来为您生成样板代码,并正确地注入每个片段。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49153037

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档