Кинжал 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 } } 

Компонент ViewHolderSubкомпонент определен ниже, цель состоит в том, чтобы создать один подкомпонент для каждого держателя вида и ввести несколько вещей:

 @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

inject(viewHolder: RecyclerView.ViewHolder) всегда будет no-op, потому что классы framework (или большинство библиотек в этом случае) не содержат никаких аннотированных полей @Inject . Кинжал будет генерировать код только для класса, указанного в ваших методах 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 .

 @set:Inject lateinit var myVar: Type 

В качестве альтернативы вы можете рассмотреть инъекции конструктора. Подобно этому вы можете определить свойства как val и private.

Intereting Posts
Объясните, почему показано предупреждение. Не отмечен ли источник-источник.readArrayList (data !!. JavaClass.classLoader) как ArrayList <Data>? Система не может найти файл, указанный в Kotlin Добавление перехватчика к уже созданному клиенту okHttp3 Могу ли я использовать имя лямбда в качестве параметра, переданного «вне круглых скобок»? java.awt.HeadlessException запуска приложения JavaFX от Kotlin REPL Мы должны покрывать все ветви всеми выражениями Control-Flow в Котлине? Java Лямбда в Котлин Почему этот код не был возвращен на этикетке в Котлине В чем разница между основной и регулярной функцией? Генераторы Java / Kotlin Как я могу построить SQL-запрос с динамическим именем столбца в пространственной постоянной библиотеке Как проверить класс «instanceof» в kotlin? Android Studio демонстрирует предупреждение зависимостей Kotlin после второй сборки Доступ к Spek для внутренних видимых классов Kotlin Android – SharedPreferences – Контекст