使用RecyclerView构建灵活的列表界面

  • Post author:
  • Post category:其他


图片

1. 引言

在现代移动应用中,列表界面是最常见的用户界面之一,它能够展示大量的数据,让用户可以浏览和操作。无论是社交媒体的动态流、商品展示、新闻列表还是任务清单,列表界面都扮演着不可或缺的角色。在构建这些界面时,开发者需要考虑到性能、交互和用户体验等方面的挑战。

本文将介绍使用Android的RecyclerView控件来构建灵活且高性能的列表界面。RecyclerView是Android官方提供的用于展示大量数据的控件,它的强大性能和灵活性使得开发者能够构建出更加流畅和功能丰富的列表界面。

2. 列表界面的挑战

在移动应用中,列表界面是常见且重要的组成部分,无论是社交媒体应用中的朋友圈、电子商务应用的商品列表,还是任务管理应用中的任务列表,列表界面都扮演着关键的角色。然而,设计和实现列表界面并不是一项简单的任务,它们面临着一些独特的挑战和复杂性。


多样性的挑战:

移动应用的用户群体多样,他们有着不同的需求和偏好。因此,开发者需要设计和实现适应各种用户需求的列表界面。一些用户可能偏好简洁的布局和少量信息,而另一些用户可能喜欢更多的细节和交互元素。这就需要在界面设计上考虑到多样性,以满足不同用户的期望。


性能的挑战:

列表界面通常需要展示大量的数据项,而移动设备的资源相对有限。因此,在设计列表界面时需要考虑性能问题,以确保列表的流畅滑动和快速响应。加载过多的数据项或者在列表项中嵌套复杂的布局都可能导致卡顿和性能下降,影响用户体验。


交互的挑战:

用户在列表界面中常常需要进行各种交互操作,如点击、滑动、长按等。开发者需要确保这些交互操作能够被准确捕捉并响应,从而提供流畅的用户体验。同时,某些交互操作可能会触发数据的变化,因此需要确保数据的一致性和正确性。


适应性的挑战:

移动设备具有不同的屏幕尺寸、分辨率和屏幕比例。因此,列表界面需要具备适应性,以在不同设备上呈现出良好的视觉效果。开发者需要考虑如何在不同屏幕上合理分配空间、调整布局和字体大小,以确保界面的可用性和美观性。


数据更新的挑战:

在很多情况下,列表界面需要及时更新数据,如在社交媒体应用中看到最新的动态,或者在电子商务应用中查看商品的库存情况。数据的及时性和准确性都是关键。开发者需要设计合适的机制来处理数据的更新和刷新,同时保证不会造成界面的混乱或闪烁。

在面对这些挑战时,开发者需要综合考虑用户体验、性能、交互和设计等多个方面,以确保列表界面能够达到预期的效果并满足用户的需求。在设计和实现过程中,选择合适的UI组件和技术是至关重要的。在接下来的内容中,我们将介绍如何使用RecyclerView来构建灵活的列表界面,以解决上述挑战并提供出色的用户体验。

3. RecyclerView介绍

图片

RecyclerView是Android的一个控件,用于展示大量的数据项,并且可以通过自定义布局来控制它们的显示。与传统的ListView相比,RecyclerView提供了更多的灵活性和性能优势。它允许开发者通过定制不同的组件来实现各种效果,如分组、瀑布流布局等。

在移动应用中,展示大量数据的列表是一项常见的任务。为了有效地处理数据的展示和交互,Android平台引入了RecyclerView控件。RecyclerView是一个强大且灵活的UI组件,专门用于展示可滚动的列表或网格布局。相较于传统的ListView,RecyclerView在性能和灵活性方面提供了显著的改进。


与ListView的区别:

ListView是Android平台早期用于展示列表数据的控件,但它在一些方面存在限制。ListView的适配器模式相对固定,导致在处理不同类型的列表项或者复杂的布局时较为繁琐。此外,ListView的绘制和布局性能在处理大量数据时可能出现问题,影响用户体验。

RecyclerView的设计更加灵活,它采用了ViewHolder模式,能够有效地重用视图并优化绘制性能。同时,RecyclerView提供了更强大的布局管理器,可以轻松实现线性列表、网格布局、瀑布流等各种布局样式。这使得开发者能够更加轻松地实现不同样式的列表界面,满足不同需求。


高性能和灵活性:

RecyclerView的高性能得益于其ViewHolder的复用机制和内部的数据更新机制。ViewHolder用于绑定视图和数据,有效地减少了视图创建和销毁的开销。此外,RecyclerView的LayoutManager负责控制布局,可以针对不同的布局需求进行优化,避免了无效的布局计算。

RecyclerView还允许开发者对列表项之间的动画进行自定义,提升用户体验。它提供了方便的ItemAnimator接口,可以轻松实现插入、删除、移动等操作时的动画效果,使列表项的变化更加生动。

在下一节中,我们将深入探讨RecyclerView的使用方式,以及如何通过RecyclerView来构建具有灵活性和高性能的列表界面。

4. RecyclerView的基本组件

RecyclerView的核心组件包括LayoutManager、Adapter和ItemDecoration。LayoutManager负责定义列表项的布局方式,Adapter负责提供数据和创建列表项的视图,ItemDecoration负责为列表项添加分隔线、边距等效果。

4. RecyclerView的基本组件

RecyclerView是由多个重要的组件组成的,每个组件都有特定的作用,协同工作以实现高效的列表展示和交互。以下是RecyclerView的基本组件:


LayoutManager:

LayoutManager负责决定RecyclerView中列表项的布局方式和排列方式。它决定了列表是线性的、网格状的还是瀑布流式的。Android提供了几种内置的LayoutManager,如:

  • • LinearLayoutManager:线性布局,支持水平和垂直排列。

  • • GridLayoutManager:网格布局,支持行数和列数的设置。

  • • StaggeredGridLayoutManager:瀑布流布局,支持不同大小的网格项。

// 创建线性布局管理器
val linearLayoutManager = LinearLayoutManager(context)
recyclerView.layoutManager = linearLayoutManager

// 创建网格布局管理器
val gridLayoutManager = GridLayoutManager(context, 2) // 2列
recyclerView.layoutManager = gridLayoutManager


Adapter:

Adapter负责将数据绑定到RecyclerView的每个列表项上,并将列表项交给RecyclerView来显示。开发者需要实现自定义的Adapter继承自RecyclerView.Adapter,并在其中实现数据绑定逻辑。

class MyAdapter(private val data: List<String>) : RecyclerView.Adapter<MyViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
        return MyViewHolder(view)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val itemData = data[position]
        holder.bind(itemData)
    }

    override fun getItemCount(): Int {
        return data.size
    }
}


ItemDecoration:

ItemDecoration用于在列表项之间添加分隔线或者其他装饰。它可以为列表项提供更好的视觉分隔和组织。

class MyItemDecoration(private val spacing: Int) : RecyclerView.ItemDecoration() {
    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        outRect.left = spacing
        outRect.right = spacing
        outRect.bottom = spacing

        // Add top margin to the first item
        if (parent.getChildAdapterPosition(view) == 0) {
            outRect.top = spacing
        }
    }
}

通过这些基本组件的协作,RecyclerView能够实现各种复杂的列表界面,从简单的垂直线性列表到多列网格布局,再到瀑布流式的交错布局。在下一节,我们将探讨如何使用这些组件来构建一个完整的RecyclerView列表界面。

5. 创建RecyclerView

图片

在这一部分,我们将学习如何在Android应用中创建一个基本的RecyclerView,展示如何在布局文件中定义RecyclerView以及如何编写适当的代码来创建Adapter和ViewHolder。


5.1 布局文件中定义RecyclerView

首先,在你的布局文件中添加一个RecyclerView控件:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


5.2 创建Adapter和ViewHolder

接下来,我们需要创建一个Adapter来绑定数据到RecyclerView的每个列表项,并创建一个ViewHolder来管理列表项的视图。

class MyAdapter(private val data: List<String>) : RecyclerView.Adapter<MyViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
        return MyViewHolder(view)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val itemData = data[position]
        holder.bind(itemData)
    }

    override fun getItemCount(): Int {
        return data.size
    }
}

class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val textView: TextView = itemView.findViewById(R.id.textView)

    fun bind(data: String) {
        textView.text = data
    }
}


5.3 将Adapter设置给RecyclerView

在Activity或Fragment中,你可以这样设置Adapter给RecyclerView:

val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
val adapter = MyAdapter(dataList) // dataList是你的数据列表
recyclerView.adapter = adapter

通过上述代码,你就成功地创建了一个基本的RecyclerView,并将数据绑定到了列表项的视图上。在下一节,我们将继续探讨如何添加布局管理器和分隔线,以及如何处理列表项的点击事件。

6. 使用不同的LayoutManager

在这一部分,我们将研究RecyclerView的不同LayoutManager类型,它们可以帮助我们控制列表项的布局方式。以下是几种常用的LayoutManager类型:



  • LinearLayoutManager:

    用于在垂直或水平方向上排列列表项,类似于传统的ListView布局。



  • GridLayoutManager:

    用于在网格状布局中排列列表项,你可以指定列数。



  • StaggeredGridLayoutManager:

    类似于GridLayoutManager,但是不同列的列表项可以有不同的高度,创造出瀑布流式的效果。

你可以根据不同的布局需求来选择适当的LayoutManager。以下是一个设置LayoutManager的示例代码:

val layoutManager = LinearLayoutManager(this) // 或者 GridLayoutManager 或 StaggeredGridLayoutManager
recyclerView.layoutManager = layoutManager

7. 自定义ItemDecoration

在RecyclerView中,ItemDecoration用于在列表项之间添加分割线、边距等效果。你可以通过自定义ItemDecoration来实现个性化的界面风格。以下是一个简单的自定义ItemDecoration示例:

class MyItemDecoration(private val space: Int) : RecyclerView.ItemDecoration() {
    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        outRect.left = space
        outRect.right = space
        outRect.bottom = space

        // Add top margin only for the first item to avoid double space between items
        if (parent.getChildAdapterPosition(view) == 0) {
            outRect.top = space
        }
    }
}

然后,在设置Adapter之后,将自定义的ItemDecoration附加到RecyclerView上:

val itemDecoration = MyItemDecoration(16) // 设置分割线的宽度
recyclerView.addItemDecoration(itemDecoration)

通过这种方式,你可以为列表项之间添加分隔线和边距,以提升界面的美观性和可读性。在下一节,我们将讨论如何处理列表项的点击事件。

8. 实现点击和交互

图片

在这一部分,我们将学习如何处理RecyclerView列表项的点击事件,并介绍如何实现一些常见的交互效果,如拖拽排序和滑动删除。


处理列表项的点击事件

为了实现列表项的点击事件,我们需要在RecyclerView的Adapter中为列表项设置点击监听器。以下是一个示例代码,展示如何在Adapter中处理列表项的点击事件:

class MyAdapter(private val data: List<String>, private val onItemClick: (String) -> Unit) : RecyclerView.Adapter<MyViewHolder>() {

    // ... (其他必要的方法)

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val item = data[position]
        holder.bind(item)
        holder.itemView.setOnClickListener {
            onItemClick(item)
        }
    }
}

在Activity或Fragment中,我们可以这样使用Adapter并处理点击事件:

val adapter = MyAdapter(dataList) { clickedItem ->
    // 处理点击事件,例如打开新页面或显示详细信息
}
recyclerView.adapter = adapter


拖拽排序和滑动删除

RecyclerView还提供了对列表项的拖拽排序和滑动删除的支持。要实现这些效果,我们需要使用

ItemTouchHelper

类。以下是一个简单的示例,展示如何实现拖拽排序和滑动删除:

val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP or ItemTouchHelper.DOWN,
    ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
) {
    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        // 处理拖拽排序的逻辑
        return true
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        // 处理滑动删除的逻辑
    }
})
itemTouchHelper.attachToRecyclerView(recyclerView)

通过使用

ItemTouchHelper

,你可以为RecyclerView添加拖拽排序和滑动删除等交互效果,提升用户体验。

在下一节,我们将讨论如何使用RecyclerView来实现多种类型的列表项,以满足不同的布局需求。

9. 使用DiffUtil进行数据更新

在本节中,我们将学习如何使用DiffUtil来高效地更新RecyclerView中的数据,以避免不必要的刷新,从而提升性能和用户体验。


DiffUtil的作用

DiffUtil是一个Android支持库中的实用工具类,用于计算并提供数据集的差异,从而可以在列表数据更新时,只更新发生变化的部分,而不需要重新刷新整个列表。这对于大型列表和复杂的UI布局尤为有用,可以有效减少不必要的布局刷新,提升应用性能。


使用DiffUtil进行数据更新

首先,我们需要定义一个继承自

DiffUtil.ItemCallback

的类,用于比较列表中的数据项。以下是一个示例代码,展示如何创建一个DiffUtil回调类:

class MyDiffUtilCallback : DiffUtil.ItemCallback<MyData>() {
    override fun areItemsTheSame(oldItem: MyData, newItem: MyData): Boolean {
        return oldItem.id == newItem.id
    }

    override fun areContentsTheSame(oldItem: MyData, newItem: MyData): Boolean {
        return oldItem == newItem
    }
}

然后,在Adapter中使用DiffUtil来处理数据更新。以下是一个示例代码,展示如何使用DiffUtil来更新数据:

class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {

    private var dataList: List<MyData> = emptyList()

    // ... (其他必要的方法)

    fun updateData(newDataList: List<MyData>) {
        val diffResult = DiffUtil.calculateDiff(MyDiffUtilCallback(dataList, newDataList))
        dataList = newDataList
        diffResult.dispatchUpdatesTo(this)
    }
}

在数据发生变化时,我们只需要调用

updateData

方法,DiffUtil会自动计算数据集的差异,并根据差异更新列表。

使用DiffUtil可以极大地提升列表界面的性能和响应速度,特别是在数据集变化频繁的情况下。

在下一节,我们将讨论如何优化RecyclerView中的图片加载,以确保流畅的用户体验。

10. 添加动画效果

图片

在本节中,我们将学习如何为RecyclerView添加动画效果,从而增强用户界面的交互性和吸引力。


为RecyclerView添加动画效果

RecyclerView支持通过设置ItemAnimator来为列表项添加动画效果。Android提供了默认的ItemAnimator,也可以自定义动画效果以满足特定的设计需求。

以下是一些常见的动画效果:

  1. 1. 淡入淡出效果:列表项在插入和删除时以淡入和淡出的方式出现和消失。

  2. 2. 平移效果:列表项在插入和删除时以平移的方式进入和退出列表。


示例:使用默认的ItemAnimator

RecyclerView的默认ItemAnimator提供了简单但有效的插入、删除和更新动画效果。以下是如何使用默认ItemAnimator的示例代码:

val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
val adapter = MyAdapter()
recyclerView.adapter = adapter

val defaultItemAnimator = DefaultItemAnimator()
recyclerView.itemAnimator = defaultItemAnimator


示例:自定义动画效果

如果需要更加定制化的动画效果,我们可以自定义ItemAnimator。以下是一个示例,展示如何自定义一个平移的ItemAnimator:

class TranslateItemAnimator : DefaultItemAnimator() {

    override fun animateAdd(holder: RecyclerView.ViewHolder?): Boolean {
        if (holder != null) {
            holder.itemView.translationY = 300f
            ViewCompat.animate(holder.itemView)
                .translationY(0f)
                .setDuration(addDuration)
                .setInterpolator(overshootInterpolator)
                .setListener(DefaultAddAnimatorListener(holder))
                .start()
            return false
        }
        return super.animateAdd(holder)
    }
}

在使用自定义的ItemAnimator时,我们需要创建一个继承自

RecyclerView.ItemAnimator

的类,并实现相应的动画逻辑。

通过添加动画效果,可以让列表界面更加生动有趣,提升用户体验。

在下一节,我们将讨论如何处理RecyclerView中的用户输入事件,以实现更加丰富的交互效果。

11. 加载大数据集和分页加载

在本节中,我们将探讨在RecyclerView中加载大数据集或实现分页加载时的策略,以及如何确保应用的性能和用户体验。


加载大数据集

当列表中包含大量数据项时,一次性加载所有数据可能会导致内存占用过高,从而影响应用的性能。为了解决这个问题,我们可以采用分页加载的方式,将数据分为多个页面进行加载。


分页加载策略

分页加载是一种在列表滚动到底部时加载新数据的策略,以保持用户体验流畅。以下是一种简单的分页加载策略:

  1. 1. 定义每页的数据量,如每页加载10个数据项。

  2. 2. 监听RecyclerView的滚动事件,当滚动到底部时触发加载下一页的数据。

  3. 3. 加载新数据后,更新适配器并通知RecyclerView数据集发生变化。


示例:分页加载

以下是一个示例,展示如何使用分页加载策略来加载数据:

class MyAdapter(private val dataList: MutableList<DataItem>) : RecyclerView.Adapter<MyViewHolder>() {

    // ... other adapter methods

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        // Bind data to the view holder
    }

    override fun getItemCount(): Int {
        return dataList.size
    }

    // Load next page of data
    fun loadNextPage(newData: List<DataItem>) {
        val startPosition = dataList.size
        dataList.addAll(newData)
        notifyItemRangeInserted(startPosition, newData.size)
    }
}

在实际应用中,我们可以根据需要调整分页加载的逻辑,确保数据加载时的流畅性和用户体验。

通过加载大数据集和实现分页加载,我们可以更好地管理大量数据,提升应用性能,并为用户提供流畅的浏览体验。

在接下来的章节,我们将探讨一些高级技巧,以进一步优化RecyclerView的使用和效果。

12. 性能优化

图片

在本节中,我们将探讨如何对RecyclerView进行性能优化,以确保列表界面的流畅性和响应性。性能问题可能会影响用户体验,因此在开发列表界面时需要特别关注。


1. ViewHolder的复用

ViewHolder的复用是提高RecyclerView性能的关键。通过复用ViewHolder,可以避免频繁地创建和销毁视图,从而减少内存开销和UI刷新的成本。

class MyAdapter(private val dataList: List<DataItem>) : RecyclerView.Adapter<MyViewHolder>() {

    // ... other adapter methods

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
        return MyViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        // Bind data to the view holder
    }
}


2. 图片加载优化

在列表中加载大量图片可能会影响性能。为了优化图片加载,可以考虑使用图片加载库,如Glide或Picasso,以实现异步加载、缓存和图片裁剪。

// Using Glide for image loading
Glide.with(context)
    .load(imageUrl)
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error_image)
    .into(imageView)


3. 减少不必要的布局层级

布局层级的增加会导致UI绘制成本上升。在设计布局时,尽量减少嵌套的布局层级,使用ConstraintLayout等高效的布局容器。


4. 使用DiffUtil进行数据更新

在前面的章节中,我们已经介绍了DiffUtil的使用。通过DiffUtil,可以避免不必要的数据更新,提高性能。

class MyAdapter(private val oldList: List<DataItem>, private val newList: List<DataItem>) :
    RecyclerView.Adapter<MyViewHolder>() {

    // ... other adapter methods

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        // Bind data to the view holder
    }

    // Update data using DiffUtil
    fun updateData(newList: List<DataItem>) {
        val diffResult = DiffUtil.calculateDiff(DataDiffCallback(oldList, newList))
        this.oldList.clear()
        this.oldList.addAll(newList)
        diffResult.dispatchUpdatesTo(this)
    }
}

通过以上性能优化措施,我们可以有效地提高RecyclerView在列表界面中的性能,为用户提供更加流畅和快速的体验。 总之,使用RecyclerView作为构建列表界面的核心控件,能够帮助开发者在解决性能、交互和用户体验等方面的挑战。它的灵活性和高性能使得开发者能够轻松地实现各种不同类型的列表界面,从而为用户提供更好的应用体验。

13. 结论

图片

通过本文的探讨,我们深入了解了如何使用RecyclerView构建灵活且高性能的列表界面。RecyclerView作为Android平台上的一个重要控件,为我们提供了强大的工具来展示各种类型的数据,并允许我们在列表界面中实现各种交互和动画效果。在结尾部分,我们将总结所学内容并鼓励开发者积极应用这些知识。


优势和技巧

RecyclerView相对于ListView等传统控件具有明显的优势。它不仅在性能上更出色,还提供了更灵活的布局管理、交互效果以及数据更新方式。在构建列表界面时,我们可以采用以下技巧来充分发挥RecyclerView的优势:

  • • 使用ViewHolder的复用,减少视图的创建和销毁,提高内存和性能效率。

  • • 选择适当的LayoutManager来满足不同的布局需求,如线性列表、网格布局和瀑布流布局等。

  • • 使用ItemDecoration自定义分割线、边距等视觉效果,以增强界面的美观性。

  • • 利用DiffUtil进行数据更新,避免不必要的刷新,提高数据更新的效率。

  • • 添加动画效果以增加用户体验,但要注意不要过度使用,以免影响性能。


鼓励创新和优化

RecyclerView是一个强大的工具,可以满足各种不同的列表界面需求。我们鼓励开发者在设计列表界面时充分发挥创意,创造出与众不同的用户体验。同时,优化性能也是至关重要的一环,通过合理的布局设计、数据更新策略和异步加载等手段,确保列表界面在性能和用户体验上达到最佳状态。

总之,RecyclerView作为Android开发中不可或缺的一部分,将持续为我们提供强大的功能和灵活性。通过合理的应用和不断的优化,我们可以构建出功能强大、性能卓越的列表界面,为用户带来出色的移动应用体验。

14. 参考资料

在本文中,我们涵盖了使用RecyclerView构建灵活的列表界面的各个方面。以下是一些相关的参考资料和资源,供您进一步深入学习和探索:

  1. 1. RecyclerView 官方文档[1]

  2. 2. Android Developer 官方培训课程 – 使用 RecyclerView[2]

  3. 3. RecyclerView vs ListView – 选择正确的列表控件[3]

  4. 4. 使用 RecyclerView 构建复杂列表[4]

  5. 5. Android RecyclerView 教程[5]

这些资源将帮助您更深入地理解和应用RecyclerView在Android应用中的各种功能和优势。通过学习和实践,您可以成为一个更加熟练和有创意的Android开发者,构建出优雅和高性能的列表界面。

引用链接


[1]

RecyclerView 官方文档:

https://developer.android.com/guide/topics/ui/layout/recyclerview



[2]

Android Developer 官方培训课程 – 使用 RecyclerView:

https://developer.android.com/courses/pathways/android-basics-kotlin-four



[3]

RecyclerView vs ListView – 选择正确的列表控件:

https://www.raywenderlich.com/1560485-recyclerview-vs-listview-choosing-the-right-widget



[4]

使用 RecyclerView 构建复杂列表:

https://www.raywenderlich.com/1560485-recyclerview-vs-listview-choosing-the-right-widget



[5]

Android RecyclerView 教程:

https://www.journaldev.com/24041/android-recyclerview

转自:

使用RecyclerView构建灵活的列表界面