我知道通常情况下这不应该与使用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),而不是特定的子类.