我知道通常情况下,使用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}}
答案 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.ViewHolder
和RecyclerView.ViewHolder
之间创建一个基类,但是再次,您只能在基类中注入声明(和ErrorViewHolder
注释)的字段,而不是特定的子项。
答案 1 :(得分:0)
Kotlin 预言本身并不为 Dagger 所知。您要实现的目标可以作为字段或setter注入处理。由于生成的setter具有我通常用于@set:Inject
的任何属性。
@set:Inject lateinit var myVar: Type
或者您可以考虑构造函数注射。像这样,您可以将属性定义为val
和私有。