kotlin-android-расширения в ViewHolder

class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

       fun bindata(text: SingleText){
            itemView.title.text = text.title
            itemView.desc.text = text.desc
       }
}

как этот код, Котлин имеет какой-либо кэш в Android-расширений?

когда я декомпилирую байт-код Котлина

public final void bindata(@NotNull SingleText text) {

  Intrinsics.checkParameterIsNotNull(text, "text");
  ((AppCompatTextView)this.itemView.findViewById(id.title)).setText((CharSequence)text.getTitle());
  ((AppCompatTextView)this.itemView.findViewById(id.desc)).setText((CharSequence)text.getDesc());

}

это означает, когда я вызвал Bindata в адаптере.onBindViewHolder (), он будет называться findViewById каждый раз

это значительно увеличивает потерю производительности, и это не достигает цели повторного использования макета

Kotlin имеет логику кэша в android-расширениями с ViewHolder?

3 ответов


просмотр кэширования в ViewHolder или любой пользовательский класс возможен только из Котлин 1.1.4 и в настоящее время он находится в экспериментальной стадии.

  1. обновите версию Kotlin в сборке корневого уровня.файл gradle

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.4-3"

  1. добавьте эти строки в приложение build.gradle:

androidExtensions { experimental = true }

  1. наследовать ваш ViewHolder класс LayoutContainer. LayoutContainer - это интерфейс доступно в kotlinx.android.extensions пакета.

  2. добавить ниже импорта, где view_item - имя макета.

import kotlinx.android.synthetic.main.view_item.* import kotlinx.android.synthetic.main.view_item.view.*

весь ViewHolder класса выглядит так:

class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
        LayoutContainer {

    fun bind(title: String) {
        itemTitle.text = "Hello Kotlin!" // itemTitle is the id of the TextView in the layout 
    }
}

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

    public final void bind(@NotNull String title) {
          Intrinsics.checkParameterIsNotNull(title, "title");
          ((TextView)this._$_findCachedViewById(id.itemTitle)).setText((CharSequence)"Hello Kotlin!");
    }

дополнительные материалы: сохранить предложение, удивительный учебник.


из моего понимания, kotlin-android-extensions - это просто статически импортированное расширение (сгенерированные коды) для замены представления.команду findViewById.

Я бы рекомендовал вам сохранить ссылки в держателе представления.

class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
   val title: TextView = itemView.title
   val desc: TextView = itemView.desc

   fun bindata(text: SingleText){
       title.text = text.title
       desc.text = text.desc
   }
}

одним из преимуществ этого подхода является несоответствие любого типа, которое будет обнаружено во время компиляции!


в вашем проекте gradle: -

 buildscript {
        ext.kotlin_version = '1.2.41'

        repositories {
            google()
            jcenter()
        }

и в вашем приложении gradle:

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {}
dependencies {
  compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

после этого вы можете использовать в своей деятельности:

import kotlinx.android.synthetic.main.unit_preferences_activity.*

и:

  private fun setClickListener() {
            rlCaloriesBurnt.setOnClickListener{
                launchActivity(CaloriesBurntPrefreenceUnit::class.java)
            }

            rlDistanceTravelled.setOnClickListener{

           tvDistanceUnit.text=resources.getString(R.string.km)

                launchActivity(DistanceTravelledUnit::class.java)
            }

            rlWaterConsumption.setOnClickListener{
                launchActivity(WaterPreferenceUnit::class.java)
            }
            backArrow.setOnClickListener{
                finish()
            }

        }