ViewHolder 中的 kotlin-android-extensions
Posted
技术标签:
【中文标题】ViewHolder 中的 kotlin-android-extensions【英文标题】:kotlin-android-extensions in ViewHolder 【发布时间】:2018-02-07 15:49:07 【问题描述】:class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
fun bindata(text: SingleText)
itemView.title.text = text.title
itemView.desc.text = text.desc
像这段代码一样,Kotlin 在 android-extensions 中有缓存吗?
当我反编译 kotlin 字节码时
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());
这意味着当我在Adapter.onBindViewHolder()中调用binData时,每次都会调用findViewById
这显着增加了性能的损失,并没有达到布局复用的目的
Kotlin 在带有 ViewHolder 的 android-extensions 中有任何缓存逻辑吗?
【问题讨论】:
findViewById
找到已创建的视图。所以这意味着你正在重用它。没有您所说的性能问题。
【参考方案1】:
ViewHolder
或任何自定义类中的视图缓存只能来自 Kotlin 1.1.4,并且目前处于实验阶段。
-
在根级 build.gradle 文件中更新 Kotlin 版本
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.4-3"
-
在您的应用程序中添加这些行
build.gradle
:
androidExtensions
experimental = true
从LayoutContainer
继承您的ViewHolder
类。 LayoutContainer
是kotlinx.android.extensions
包中的一个接口。
添加以下导入,其中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!");
进一步阅读:KEEP proposal、an awesome tutorial。
【讨论】:
【参考方案2】:据我了解,kotlin-android-extensions 只是一个静态导入的扩展(生成的代码)来替换 View.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
这种方法的一个好处是任何类型不匹配都会在编译时被发现!
【讨论】:
如果为每个View添加一行代码,还不如不使用Kotlin Android扩展。如果将 findViewById() 包装在扩展函数中,它也将是类型安全的。val title = itemView.find<TextView>(R.id.title)
@FrankHarper 如果R.id.title
没有指向TextView,假设指向ImageView。 itemView.find<TextView>(R.id.title)
仍会编译并会导致运行时崩溃,而使用 Kotlin Android 扩展会在编译时抛出错误。【参考方案3】:
在你的项目中:-
buildscript
ext.kotlin_version = '1.2.41'
repositories
google()
jcenter()
在你的应用程序中:
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()
【讨论】:
以上是关于ViewHolder 中的 kotlin-android-extensions的主要内容,如果未能解决你的问题,请参考以下文章
ViewHolder 中的嵌套 RecyclerView 破坏了折叠工具栏布局
ViewHolder 中的 onClick 无权访问适配器中的单击项目
DataBinding:如何使用 Kotlin 中的泛型创建具有多个 ViewHolder(多个布局)的 Recyclerview
recyclerview viewholder布局中的更改约束 - android