匕首2不能从子组件(kotlin)注入

我知道,一般来说,这是使用Kotlin不应该有所作为,但我遇到了奇怪的情况,其中@Named限定符需要Kotlin中的范围如此裸露在我身边。

我有一个ViewHolderFactory类,它允许我创建一个简单的视图types – >视图持有者类的映射:

 @Singleton class ViewHolderFactoryImpl @Inject constructor( private val viewHolderComponentProvider: Provider ): 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.noOp().injectMembers(viewHolder); } 

没有为此子组件创建MembersInjectors 。 我无法弄清楚如何让这个工作。 我知道我应该可以注入不是由匕首创建的对象,我只是不能完全弄清楚我在这里丢失的东西。

哦,如果有帮助的话,我确实在我的AppModulesubcomponents列表中包含ViewHolderSubcomponent

inject(viewHolder: RecyclerView.ViewHolder)将永远是一个无操作,因为框架类(或在这种情况下大多数库)没有任何@Inject注释字段。 Dagger将只为您的inject(MyClass instance)方法中的类生成代码, 而不是它的任何子types

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

您将不得不修改您的安装程序,以便您可以提供可注入特定的查看者的特定子组件,但不能为不同types使用一个“通用”组件。 你可以在RecyclerView.ViewHolderErrorViewHolder之间创建一个基类,但是再一次,你只能在你的基类中注入声明的域(而@Inject注释),而不是特定的子类。

匕首本身并不知道科特林的神秘力量。 你试图达到的目标可以作为一个领域或二传手注入。 由于setter是通过任何属性生成的,我通常会使用@set:Inject

 @set:Inject lateinit var myVar: Type 

或者,您可以考虑构造函数注入。 像这样你可以定义属性为val和private。