android – 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值为null.查看生成的代码,我可以看到原因:

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

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

哦,如果它有帮助,我确实在我的AppModule的子组件列表中包含ViewHolderSubcomponent

最佳答案 inject(viewHolder:RecyclerView.ViewHolder)将永远是一个无操作,因为框架类(或在这种情况下大多数库)没有任何@Inject注释字段. Dagger只会为您的inject(MyClass实例)方法中指定的类生成代码,而不会为其任何子类型生成代码.

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

您必须稍微修改您的设置,以便您可以提供可以注入特定视图的特定子组件,您不能为不同类型使用一个“通用”组件.您可以在RecyclerView.ViewHolder和ErrorViewHolder之间创建一个基类,但是再次,您只能在基类中注入声明的字段(和@Inject annotated),而不是特定的子类.

点赞