Кинжал 2 не может вводить из подкомпонента
Я знаю, что в общем случае не должно иметь значения, что это использует Kotlin, но я столкнулся с странными случаями, когда @Named
квалификатору нужна была сфера в Котлине.
у меня есть 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
список subcomponents
2 ответа
inject(viewHolder: RecyclerView.ViewHolder)
всегда будет неактивным, потому что у каркасных классов (или большинства библиотек в этом случае) нет @Inject
аннотированные поля. Dagger будет генерировать код только для класса, указанного в вашем inject(MyClass instance)
методы, а не для любого из его подтипов.
Так что если у вас есть ErrorViewHolder : RecyclerView.ViewHolder
то вы должны использовать компонент, который имеет inject(ErrorViewHolder instance)
метод для генерации кода для внедрения ErrorViewHolder
,
Чтобы уточнить, потому что это сгенерированный код - а не динамическое отражение во время выполнения - вызов inject(viewHolder: RecyclerView.ViewHolder)
как вы делаете с viewHolder : ErrorViewHolder
все еще будет пытаться ввести поля для RecyclerView.ViewHolder
не ErrorViewHolder
, А также RecyclerView.ViewHolder
всегда будет неактивным, как уже упоминалось.
Вам нужно будет немного изменить свою настройку, чтобы вы могли предоставить конкретный подкомпонент, который может внедрить определенный видоискатель, вы не можете использовать один "универсальный" компонент для разных типов. Вы можете создать базовый класс между RecyclerView.ViewHolder
а также ErrorViewHolder
, но опять же, вы можете только ввести объявленные поля (и @Inject
аннотировано) в вашем базовом классе, а не конкретный ребенок.
Сама пропасть Котлина не известна Даггеру. То, что вы пытаетесь достичь, может быть обработано как инъекция поля или сеттера. Поскольку сеттер генерируется с любым свойством, я обычно @set:Inject
,
@set:Inject lateinit var myVar: Type
В качестве альтернативы вы можете рассмотреть конструктор инъекций. Таким образом, вы можете определить свойства как val
и личное.