Dagger 2无法从子组件中注入

时间:2017-12-13 05:17:51

标签: android kotlin dagger-2

我知道通常情况下,使用Kotlin并不会产生任何影响,但我遇到了@Named限定符需要Kotlin范围的奇怪情况。

我有一个ViewHolderFactory类,允许我创建一个简单的视图类型映射 - >查看持有者类:

@Singleton
class ViewHolderFactoryImpl @Inject constructor(
        private val viewHolderComponentProvider: Provider<ViewHolderSubcomponent.Builder>
): ViewHolderFactory(mapOf(
        R.layout.view_error to ErrorViewHolder::class.java,
        R.layout.view_soft_error to SoftErrorViewHolder::class.java,
        R.layout.view_empty to EmptyViewHolder::class.java,
        R.layout.view_loading to LoadingViewHolder::class.java,
        R.layout.item_got_it to GotItViewHolder::class.java)) {

    override fun createViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val viewHolder = super.createViewHolder(parent, viewType)
        if (viewHolder is Injectable) {
            viewHolderComponentProvider.get()
                    .viewHolder(viewHolder)
                    .build()
                    .inject(viewHolder)
        }
        return viewHolder
    }
}

ViewHolderSubcomponent定义如下,目标是能够为每个视图持有者创建一个子组件并注入一些东西:

@ViewHolderScope
@Subcomponent(modules = [ViewHolderModule::class])
interface ViewHolderSubcomponent {

    fun inject(viewHolder: RecyclerView.ViewHolder)

    fun viewHolder(): RecyclerView.ViewHolder

    @Subcomponent.Builder
    interface Builder {
        @BindsInstance
        fun viewHolder(viewHolder: RecyclerView.ViewHolder): Builder
        fun build(): ViewHolderSubcomponent
    }
}

ViewHolderModule定义为:

@Module
class ViewHolderModule {
    @Provides @ViewHolderScope
    fun provideSectionTitleViewHolder(viewHolder: RecyclerView.ViewHolder): SectionTitleViewHolder =
            SectionTitleViewHolder(viewHolder.itemView)
}

当我运行应用程序时,我发现注入不起作用,我的@Inject lateinit var值为空。查看生成的代码,我可以看到原因:

@Override
public void inject(RecyclerView.ViewHolder viewHolder) {
  MembersInjectors.<RecyclerView.ViewHolder>noOp().injectMembers(viewHolder);
}

没有为此子组件创建MembersInjectors<RecyclerView.ViewHolder>。我无法弄清楚如何使这个工作。我知道我应该能够注入不是由匕首创造的物体,我只是无法弄清楚我在这里缺少的东西。

哦,如果它有帮助,我确实将ViewHolderSubcomponent包含在AppModule的{​​{1}}

列表中

2 个答案:

答案 0 :(得分:1)

inject(viewHolder: RecyclerView.ViewHolder)将永远是一个无操作,因为框架类(或本例中的大多数库)没有任何@Inject注释字段。 Dagger只会为您inject(MyClass instance)方法中指定的类生成代码,不会为其任何子类型生成

因此,如果您有ErrorViewHolder : RecyclerView.ViewHolder,那么您必须使用具有inject(ErrorViewHolder instance)方法的组件来生成注入ErrorViewHolder的代码。
澄清一下,因为它在运行时调用inject(viewHolder: RecyclerView.ViewHolder)生成代码而不是动态反射,就像使用viewHolder : ErrorViewHolder一样,仍会尝试为RecyclerView.ViewHolder注入字段,而不是{ {1}}。 ErrorViewHolder将永远是提到的无操作。

您必须相当多地修改您的设置,以便您可以提供可以注入特定视图的特定子组件,您不能使用一个&#34; generic&#34;不同类型的组件。您可以在RecyclerView.ViewHolderRecyclerView.ViewHolder之间创建一个基类,但是再次,您只能在基类中注入声明(和ErrorViewHolder注释)的字段,而不是特定的子项。

答案 1 :(得分:0)

Kotlin 预言本身并不为 Dagger 所知。您要实现的目标可以作为字段或setter注入处理。由于生成的setter具有我通常用于@set:Inject的任何属性。

@set:Inject lateinit var myVar: Type

或者您可以考虑构造函数注射。像这样,您可以将属性定义为val和私有。