匕首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
。 我无法弄清楚如何让这个工作。 我知道我应该可以注入不是由匕首创建的对象,我只是不能完全弄清楚我在这里丢失的东西。
哦,如果有帮助的话,我确实在我的AppModule
的subcomponents
列表中包含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.ViewHolder
和ErrorViewHolder
之间创建一个基类,但是再一次,你只能在你的基类中注入声明的域(而@Inject
注释),而不是特定的子类。
匕首本身并不知道科特林的神秘力量。 你试图达到的目标可以作为一个领域或二传手注入。 由于setter是通过任何属性生成的,我通常会使用@set:Inject
。
@set:Inject lateinit var myVar: Type
或者,您可以考虑构造函数注入。 像这样你可以定义属性为val
和private。