Intereting Posts
Свойство Kotlin: «Тип параметра свойства должен использоваться в его типе приемника» Преобразование html-строки в pdf или изображение в Android Доступ к типу делегата Kotlin без экземпляра Автоматический ввод кода Kotlin в шаблон делегирования Spring Boot 2 и Kotlin (с Maven) Сокращенный синтаксис для генерации метода toString () в Котлине (для не-данных классов) почему String, разделенная с регулярной строкой в ​​Kotlin, не совпадает с Java? PropertyModel не может работать с частным полем Kotlin с get () Кнопки доступа из макета, программно раздутые в другом макете Жалоба EmptyClassBlock на Json TypeToken Выполнение не выполнено для задачи «app: copyDebugAndroidTestKotlinClasses» – Android Kotlin Build Error Как инициализировать контрольную переменную в Котлине Аномальное завершение процесса сборки в IntelliJ IDEA на Linux Mint Неразрешенная ссылка: sun.misc.MessageUtils.where Как установить метод тестового презентатора на основе возвращаемого значения Observable?

Могу ли я отложить привязку вида в адаптере с помощью расширения Kotlin Android

Kotlin Android Extensions обеспечивают способ использования идентификаторов непосредственно в Activity / fragment / Adapters. Так что я хочу, это общий способ для адаптера и оставить ответственность за просмотр привязки для пользователя адаптера вместо самого адаптера. Например :

class GenericAdapter<T>( @LayoutRes private val layoutId: Int, private var list: List<T>, inline private val bind: (View, T, Int) -> Unit) : RecyclerView.Adapter<InnerHolder>() { override fun onBindViewHolder(holder: InnerHolder?, position: Int) { holder?.containerView?.let { bind(holder.containerView, list[position], position) } } override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): InnerHolder = InnerHolder(LayoutInflater.from(parent?.context).inflate(layoutId, parent, false)) override fun getItemCount(): Int = list.size class InnerHolder( val containerView: View?) : RecyclerView.ViewHolder(containerView) } 

который я могу просто передать файл макета и связать функцию, чтобы привязать адаптер, как я хочу, без переписывания одного и того же кода для каждого файла макета с адаптером.

Но вот проблема: шаблон ViewHolder хочет устранить вызов «findViewById» каждый раз, когда ChildView раздувается. Но с моей реализацией адаптера. Он должен вызывать «findViewById» каждый раз, когда адаптер связывает представление.

Изменить: для получения подробной информации о проблеме «кеш».

Использование GenericAdapter в GenericAdapter . подобно

 override fun onCreated(savedInstanceState: Bundle?){ list.adapter = GenericAdapter<Item>(items){ view,item,position -> view.textview.text = item.text } } 

это будет декомпилировано в следующее:

  TextView var2 = (TextView)var10000.findViewById(id.textview); Intrinsics.checkExpressionValueIsNotNull(var2, "itemView.tv_text"); var2.setText((CharSequence)String.valueOf(var1)); 

Но у них есть экспериментальный инструмент с Android Extension с LayoutContainer например:

 class InnerHolder( override val containerView: View?) : RecyclerView.ViewHolder(containerView), LayoutContainer { fun bind(int: Int) { textview.text = int.toString() } } 

И это отлично использует кэшированные представления:

  TextView var10000 = (TextView)this._$_findCachedViewById(id.tv_text); 

Но проблема в том, что кэшированные представления нужны внутри области LayoutContainer. Например, эта реализация не будет работать:

 class InnerHolder( override val containerView: View?) : RecyclerView.ViewHolder(containerView), LayoutContainer { fun bind(int: Int) { this.bindInt(int) } } // some extension function outside the ViewHolder Scope. fun LayoutContainer.bindInt(int: Int) { tv_text.text = int.toString() } 

это все равно будет использовать findViewById для поиска:

  TextView var10000 = (TextView)$receiver.getContainerView().findViewById(id.tv_text); 

Итак, мой вопрос заключается в том, чтобы каким-то образом сохранить кеш и использовать Android Extension с моим адаптером, но вне сферы видимости?

Вы можете использовать вот так:

 innerHolder.apply { tv_text.text = "test" } 

он будет декомпилирован в следующее:

 TextView var10000 = (TextView)innerHolder._$_findCachedViewById(id.tv_text); var10000.setText((CharSequence)"test"); 

Вдохновленный @linx

Если я просто создаю функцию расширения для InnerHolder вместо LayoutContainer . Контекст дает Android Extension достаточную информацию для получения кэшированного представления.

 class InnerHolder( override val containerView: View?) : RecyclerView.ViewHolder(containerView), LayoutContainer { fun bind(int: Int) { this.bindInt(int) } } // some extension function outside the ViewHolder Scope. fun InnerHolder.bindInt(int: Int) { tv_text.text = int.toString() } 

Это скомпилируется в

 TextView var10000 = (TextView)$receiver._$_findCachedViewById(id.tv_text); 

и это именно то, что я хочу.