原标题: Kotlin & RecyclerView for High Performance Lists in Androidhtml
原文地址: www.andreasjakl.comandroid
原文做者: Andreas Jaklgit
RecyclerView 是在 Android 上显示滚动列表的最佳方法。它确保了高性能和平滑滚动,同时提供具备灵活布局的列表元素。结合 Kotlin 的现代语言功能,与传统的 Java 方法相比,RecyclerView 的代码开销大大下降。github
在本文中,咱们将介绍一个示例场景:维护应用程序的滚动列表,列出机器部件:“PartsList”。可是,此方案仅影响咱们使用的字符串 - 您能够针对您须要的任何用例复制此方法。数组
要开始使用,请使用 Android Studio 3+ 建立一个新的 Android 应用。确保启用 Kotlin 支持,并为 MainActivity 选择 “Empty” 模板。或者,若是您不想手动编写如下步骤的代码,请从 GitHub 下载完成的源码。缓存
Android 中的屏幕列表由多个子视图组成。每一个都有一个或多个视图的布局。例如,电子邮件应用会向您显示多封电子邮件; 这些项目中的每一项都包括主题,发件人姓名和一堆其余信息。bash
解析子视图的 XML 布局并将其扩展到类的实例中是一项消耗性能的操做。快速滑动会对手机性能形成巨大压力。目标是始终坚持每秒60帧。可是,这每帧只剩下不到17毫秒的计算时间。架构
RecyclerView 的主要技巧是从新使用列表中的子视图。一旦子视图 滚出可见区域,它就基本上被放入队列中。早晚,当新的子视图滚动时会再次用到它。而后,子视图的 UI 文本内容将被替换。下图显示了这个(简化的)RecyclerView 原理:app
不幸的是,这种有效的方法须要一些架构背景。刚开始看起来可能感到陌生。然而,一旦您拥有全部组件,就能够轻松的进行自定义。ide
使用RecyclerView须要配置/实现如下组件:
咱们的数据源是一个简单的列表/数组。该列表由自定义类的实例组成。您能够在应用程序中对这些进行硬编码,也能够动态建立它们 - 例如,基于来自在线源的 HTTP REST 请求。
Kotlin有一个很好的功能,能够简化数据类的编写。此方法适用于仅包含数据但不包含任何操做的全部类。咱们的示例数据类称为 PartData
,由于它存储有关维护应用程序的计算机部件的信息。
data class PartData ( val id: Long, val itemName: String)
复制代码
对于数据类,Kotlin自动生成全部实用程序函数:
getter
和 setter
。equals()
,hasCode()
,toString()
或 copy()
。Antonio Leiva 写了一篇很棒的文章,在相同数据类的状况下将 Java 与 Kotlin 进行比较。您能够节省大约80%的代码并仍然获得相同的结果。
您像任何其余类同样实例化 Kotlin 数据类。请注意,Kotlin 不使用 new
语句,所以咱们只使用类名并将值提供给构造函数参数。添加该代码的nCreate()
您的 MainActivity。
var partList = ArrayList<PartData>()
partList.add(PartData(100411, "LED Green 568 nm, 5mm"))
partList.add(PartData(101119, "Aluminium Capacitor 4.7μF"))
partList.add(PartData(101624, "Potentiometer 500kΩ"))
// ...
复制代码
RecyclerView 中的每一个项目都须要自定义布局。您可使用任意与 Activity 布局相同的方式建立这个文件:在 Android Studio 的 Android-style 项目视图中,打开 app > res > layout。右键单击"layout"
文件夹名称,而后选择 New > Layout resource file。建立一个名为part_list_item.xml
的布局。
对于示例用例,请使用如下属性:
LinearLayout
(垂直)match_parent
wrap_content
16dp
接下来,将两个子项添加到布局中。咱们将使用 TextView的。只要确保你给他们有用的ID,由于咱们须要这些来分配Kotlin代码中的文本:
使用 Android 5.0(API级别21)将 RecyclerView 添加到 Android 系统中。许多应用程序仍然针对 Android 4.4+,所以您一般会经过 AppCompat / Support 库使用 RecyclerView 。将最新的支持库版本(取决于您的编译SDK)包含到应用程序构建build
的依赖项中 .gradle
文件。
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support:recyclerview-v7:26.1.0'
复制代码
在咱们添加了这个定义以后,咱们能够开始编写使用RecyclerView的源代码了。
首先,建立一个名为 PartAdapter
的类 。将其放在与 MainActivity
相同的目录中 。在这个类中,建立一个名为 PartViewHolder
的嵌套类。
class PartViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(part: PartData) {
itemView.tv_part_item_name.text = part.itemName
itemView.tv_part_id.text = part.id.toString()
}
}
复制代码
该 ViewHolder 介绍了项目视图。此外,它还在 RecyclerView 中存储其位置的元数据。
本质上,咱们的 ViewHolder 实现的主要任务是将当前须要的数据绑定到先前膨胀的UI布局。每当滚动期间新项目可见时,此类确保项目的视图显示咱们指望在列表中此位置的内容。
要更新 UI,咱们建立本身的方法并将其命名为 bind()
。请注意,这不是基类的重写方法,所以咱们能够给它任何名称。做为方法参数,咱们只须要在 UI 中显示数据。在 bind()
中,咱们只是将提供的数据分配给视图项。
(从技术上讲,咱们没有绑定它,咱们只是分配数据。若是数据模型发生变化,它将不会自动更新此实现中的可见列表。)
若是您是 Kotlin 的新手,您可能想知道:咱们如何在 bind()
中访问 itemView
?它从何而来?
魔术被称为主要构造函数。在 Kotlin 中,它能够成为类标题的一部分。前面的构造函数关键字是可选的。
class PartViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { ... }
复制代码
这有什么好处的? Kotlin 自动将全部参数做为属性提供。所以,咱们没有看到属性定义和初始化。相反,咱们只是从 bind()
函数中访问该属性 。
咱们正在探索RecyclerView架构中最重要的组件:适配器。它有3个主要任务:
让咱们看一下大图中的适配器以及这3个任务适合的位置:
您没必要编写代码来手动覆盖这三个函数。只需扩展 PartAdapter 类的定义 便可。让它继承 RecyclerView 的适配器。Android Studio 会自动提示您实施全部必需的成员:
而后,将参数 “partItemList” 添加到 PartAdapter 类中。使用主构造函数。这将容许 MainActivity 在实例化 PartAdapter 时提供数据模型。
和之前同样, partItemList 参数自动做为属性使用。在咱们的例子中,属性类型是咱们的数据类的简单列表(数组)。
class PartAdapter (val partItemList: List<PartData>, val clickListener: (PartData) -> Unit) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
复制代码
Android Studio 已经建立了方法存根。咱们只需编写几行实现。此代码根据咱们的要求定制适配器,并完成我所描述的3个主要任务。
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
// LayoutInflater: takes ID from layout defined in XML.
// Instantiates the layout XML into corresponding View objects.
// Use context from main app -> also supplies theme layout values!
val inflater = LayoutInflater.from(parent.context)
// Inflate XML. Last parameter: don't immediately attach new view to the parent view group val view = inflater.inflate(R.layout.part_list_item, parent, false) return PartViewHolder(view) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { // Populate ViewHolder with data that corresponds to the position in the list // which we are told to load (holder as PartViewHolder).bind(partItemList[position]) } override fun getItemCount() = partItemList.size 复制代码
inflate()
方法的最后一个参数 确保新视图不会当即附加到父视图组。相反,它只在缓存中,不该该是可见的。partItemList
属性,咱们调用咱们添加到 ViewHolder 的自定义 bind()
函数。咱们差很少完成了。接下来,咱们建立 RecyclerView。第一步是将其添加到 MainActivity 的 XML 布局定义中。
若是您使用 Android Studio 的新项目向导并建立了一个空活动,则会添加一个 “Hello World” TextView。删除它。
而是为具备ID “rv_parts” 的滚动全屏 RecyclerView 列表添加如下定义:
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_parts"
android:layout_width="match_parent"
android:layout_height="match_parent" />
复制代码
在MainActivity的 onCreate()
中只须要三行代码 。
rv_parts.layoutManager = LinearLayoutManager(this)
复制代码
rv_parts.hasFixedSize()
复制代码
rv_parts.adapter = PartAdapter(testData)
复制代码
如今按下播放,您的RecyclerView应该能够正常工做!使用咱们提供的三个示例数据项,列表有点过短,没法彻底理解滚动。要测试它,只需使用一些额外的项目扩展列表。
如今您已经掌握了基础知识,能够很容易地扩展项目布局和数据类以及其余信息。
若是某些内容不适合您,请将您的代码与 GitHub 上的完成解决方案进行比较。请注意,解决方案比咱们在此阶段更先进 - 例如,它已经包含单击处理程序。
缺乏一个常用的部分:点击处理程序。与 ListView 相比,这些在 RecyclerViews 中要复杂得多。可是,若是作得好,他们很容易添加 Kotlin。这只是了解一些更先进的 Kotlin 概念的问题。咱们将在下一部分看一下这个!