RecyclerView 是一款很是强大的 widget,它能够帮助您灵活地显示列表数据。当我开始学习 RecyclerView 的时候,我发现对于复杂的列表界面有不少资源能够参考,可是对于简单的列表展示就鲜有可参考的资源了。虽然 RecyclerView 的组成结构乍一看有些复杂,可是深刻理解之后您会发现它其实很是简单明了。android
本文会经过建立一个简单的 RecyclerView 实现一个列表来显示不一样种类的花的名字。在实现的过程当中,我也会将 RecyclerView 的每一个部分揉碎了展示给你们,这样你们就能够在本身的应用中实现了。git
RecyclerView 是一个容器,它用于显示列表形式 (list) 或者网格形式 (grid) 的数据,好比文本或者照片。github
当列表滑动的时候,实际上只有少许邻近的视图会显示在屏幕上。当视图滑出屏幕时,RecyclerView 会复用它而且填充新的数据。因为它是经过回收已有的结构而不是持续建立新的列表项,因此它能够有效提升应用的时间效率和空间效率。数据库
粉红色的方格表示屏幕上正在显示的表项,黄色的方格表示屏幕可视范围以外的表项是如何被回收并转为新的视图
为何您须要使用 RecyclerView 呢?数组
总之,RecyclerView 兼顾了灵活性和个性化,因此它是功能强大的工具。缓存
本文会为你们展现如何实现一个简单的 RecyclerView
,用它来显示不一样种类花的名称。下面的代码会使用 Kotlin 语言,可是 RecyclerView
也能够在 Java 语言中使用。网络
首先在 Android Studio 里建立一个工程,而且使用 Empty Activity 模板。设置项目名称,而且选择 Kotlin 做为项目所用的语言。app
接下来在 app 级的 build.gradle
文件里引入 最新版本 的 RecyclerView
依赖。ide
2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> // 在 https://developer.android.google.cn/jetpack/androidx/releases/recyclerview 得到最新版本号 def recyclerview_version = "1.1.0" implementation 'androidx.recyclerview:recyclerview:$recyclerview_version
RecyclerView
最重要的组成部分之一就是须要显示的数据。对于比较复杂的应用来讲,数据多是来自数据库或者来自于网络,不过这里咱们简单使用字符串资源文件做为应用的数据源。函数
在 strings.xml
文件中,建立一个字符串数组来存放花的名称。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> <resources> <string name="app_name">RecyclerSample</string> <string-array name="flower_array"> <item>Lily</item> <item>Poppy</item> <item>Sunflower</item> <item>Freesia</item> <item>Daisy</item> <item>Rose</item> <item>Daffodil</item> <item>Lavender</item> <item>Peony</item> <item>Lilac</item> <item>Dahlia</item> <item>Tulip</item> <item>Dandelion</item> <item>Geranium</item> <item>Gardenia</item> <item>Rhododendron</item> <item>Azalea</item> </string-array> </resources>
而后,建立一个类,名字为 Datasource
,而且能够接收一个 Context 类型的参数。建立一个叫作 getFlowerList()
的函数,它负责返回花的名称列表。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class Datasource(val context: Context) { fun getFlowerList(): Array<String> { return context.resources.getStringArray(R.array.flower_array) } }
在 MainActivity.onCreate()
中,建立一个变量叫作 flowerList
,而后将 getFlowerList()
的返回结果赋给它。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val flowerList = Datasource(this).getFlowerList() }
接下来,在 activity_main
布局文件中将 TextView
替换为 RecyclerView
,而且将其 layoutManager
设置为 LinearLayoutManager
。使用 LinearLayoutManager
意味着将来数据将以纵向列表或者横向列表的形式显示 (默认是纵向列表)。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="LinearLayoutManager"/> </FrameLayout>
上面的示意图表示一个包含数据表项的 RecyclerView
。在这里,组成 RecyclerView
的表项 (Item) 里会包含花的名称。
建立一个新的布局文件,将它命名为 flower_item
,它用来决定每个表项的显示布局。本例中布局仅须要显示一个鲜花的名称,因此这里只须要 TextView
。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/flower_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="32sp" /> </FrameLayout>
接下来是 RecyclerView
的重头戏了,也就是 ViewHolder 和 Adapter 类。ViewHolder 负责存储 RecyclerView 中每个单独的表项所须要显示的信息。RecyclerView 仅须要建立当前所显示的表项数量的 ViewHolder 外加缓存中的几个 ViewHolder 便可。随着用户滑动屏幕,ViewHolder会被回收 (使用新数据进行填充),已有的表项会在一端消失,而且在另外一端显示一个新的表项。Adapter 类从数据源得到数据,而且将数据传递给正在更新其所持视图的 ViewHolder。下图显示了 RecyclerView、Adapter、ViewHolder 和数据之间的协做关系。
建立 Adapter
建立一个叫作 FlowerAdapter 的类,所需显示的列表数据做为该类的参数。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class FlowerAdapter(val flowerList: Array<String>) { }
建立 ViewHolder
建立一个叫作 FlowerViewHolder 的内部类,而且它能够接收一个 itemView 做为参数。在 ViewHolder 中,建立一个变量来引用 TextView,而后将它指向表项布局里对应的视图。而后建立 bind() 函数,它用来将花的名字 (字符串) 和携带数据的 UI (flowerTextView) 关联起来。bind() 函数接收传入的字符串,而且将字符串做为 flowerTextView 的文本内容。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class FlowerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){ private val flowerTextView:TextView = itemView.findViewById(R.id.flower_text) fun bind(word: String){ flowerTextView.text = word } }
继承 RecyclerView.Adapter
更新 FlowerAdapter 的类定义,使其继承 RecyclerView.Adapter 类,而且将 FlowerViewHolder做为参数传入。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class FlowerAdapter(val flowerList: Array<String>) : RecyclerView.Adapter<FlowerAdapter.FlowerViewHolder>() { }
重写 RecyclerView.Adapter
的类须要重写三个方法 onCreateViewHolder()
、onBindViewHolder()
和 getItemCount()
。
重写 onCreateViewHolder()
当 ViewHolder
建立的时候会调用该方法。在该方法里进行初始化和填充 RecyclerView
中的表项视图。该视图使用前面咱们建立的用于显示文本的布局。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FlowerViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.flower_item, parent, false) return FlowerViewHolder(view) }
重写 onBindViewHolder()
onBindViewHolder()
被调用的时候,会传入参数 ViewHolder
和一个位置 (position),它表示在 flowerList 中所绑定的表项的位置。该位置能够用于提取表项所需的数据,而且将数据传递给 ViewHolder 来使数据绑定到对应的 UI。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun onBindViewHolder(holder: FlowerViewHolder, position: Int) { holder.bind(flowerList[position]) }
重写 getItemCount()
RecyclerView 显示一个列表,因此它须要知道列表里共有多少项。因为 flowerList 就是数据源,因此直接返回它的长度便可。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun getItemCount(): Int { return flowerList.size }
完成 Adapter 代码
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class FlowerAdapter(val flowerList: Array<String>) : RecyclerView.Adapter<FlowerAdapter.FlowerViewHolder>() { // 描述表项视图而且将它放在 RecyclerView 中 class FlowerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private val flowerTextView: TextView = itemView.findViewById(R.id.flower_text) fun bind(word: String) { flowerTextView.text = word } } // 返回一个新的 ViewHolder override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FlowerViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.flower_item, parent, false) return FlowerViewHolder(view) } // 返回数据列表的长度 override fun getItemCount(): Int { return flowerList.size } // 显示一个指定位置的数据 override fun onBindViewHolder(holder: FlowerViewHolder, position: Int) { holder.bind(flowerList[position]) } }
咱们已经建立了布局、数据列表和 adapter。如今咱们能够将 RecyclerView
添加到 MainActivity
,而且将 Adapter
赋值给它。
定义一个变量叫作 recyclerView
,而后将 activity_main
中的 RecyclerView
赋值给 recyclerView
。将 FlowerAdapter
做为您 recyclerView
的 adapter。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val flowerList = Datasource(this).getFlowerList() val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.adapter = FlowerAdapter(flowerList) } }
如今咱们运行一下,而后看看它操做起来如何:
完整代码请点击 这里。
上面的例子为你们展现了如何实现 RecyclerView 的几个组成部分来显示简单的文本元素。固然 RecyclerView 能够包含更多有趣和复杂的元素,咱们将在将来的文章和示例中为你们展现。
更多资源,请参阅: