将 RecyclerView 迁移到 Lazy 列表

RecyclerView 是一种 View 组件,可以轻松高效地显示大量数据。而不是为数据集中的每个项目创建视图,RecyclerView 通过保持少量视图池并在您滚动浏览这些项目时循环使用它们来提高应用程序的性能。

在 Compose 中,您可以使用 Lazy 列表 来实现相同的功能。此页面介绍了如何将您的 RecyclerView 实现迁移到在 Compose 中使用 Lazy 列表。

迁移步骤

要将您的 RecyclerView 实现迁移到 Compose,请按照以下步骤操作

  1. 注释掉或从 UI 层次结构中删除 RecyclerView,并添加一个 ComposeView 来替换它(如果层次结构中还没有)。这是您将添加的 Lazy 列表的容器

          <FrameLayout
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    
      <!--    <androidx.recyclerview.widget.RecyclerView-->
      <!--            android:id="@+id/recycler_view"-->
      <!--            android:layout_width="match_parent"-->
      <!--            android:layout_height="match_parent />"-->
    
              <androidx.compose.ui.platform.ComposeView
                  android:id="@+id/compose_view"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" />
    
          </FrameLayout>
    
  2. 根据您的 RecyclerView 的布局管理器确定您需要哪种类型的 Lazy 列表可组合项(请参见下表)。您选择的可组合项将是您在上一步中添加的 ComposeView 的顶级可组合项。

    布局管理器

    可组合项

    LinearLayoutManager

    LazyColumnLazyRow

    GridLayoutManager

    LazyVerticalGridLazyHorizontalGrid

    StaggeredGridLayoutManager

    LazyVerticalStaggeredGridLazyHorizontalStaggeredGrid

    // recyclerView.layoutManager = LinearLayoutManager(context)
    composeView.setContent {
        LazyColumn(Modifier.fillMaxSize()) {
            // We use a LazyColumn since the layout manager of the RecyclerView is a vertical LinearLayoutManager
        }
    }

  3. RecyclerView.Adapter 实现中的每种视图类型创建一个对应的可组合项。每种视图类型通常映射到一个 ViewHolder 子类,尽管并非总是如此。这些可组合项将用作列表中不同类型元素的 UI 表示

    @Composable
    fun ListItem(data: MyData, modifier: Modifier = Modifier) {
        Row(modifier.fillMaxWidth()) {
            Text(text = data.name)
            // … other composables required for displaying `data`
        }
    }

    您在 RecyclerView.AdapteronCreateViewHolder()onBindViewHolder() 方法中的逻辑将由这些可组合项以及您提供给它们的状态替换。在 Compose 中,创建项目的可组合项和将数据绑定到其中之间没有区别——这些概念是合并的。

  4. 在 Lazy 列表的 content 插槽(尾随 lambda 参数)中,使用 items() 函数(或等效的重载)遍历列表的数据。在 itemContent lambda 中,为您的数据调用适当的可组合项

    val data = listOf<MyData>(/* ... */)
    composeView.setContent {
        LazyColumn(Modifier.fillMaxSize()) {
            items(data) {
                ListItem(it)
            }
        }
    }

常见用例

项目装饰

RecyclerView 有一个 ItemDecoration 的概念,您可以使用它为列表中的项目添加特殊绘制。例如,您可以添加一个 ItemDecoration 来在项目之间添加分隔线

val itemDecoration = DividerItemDecoration(recyclerView.context, LinearLayoutManager.VERTICAL)
recyclerView.addItemDecoration(itemDecoration)

Compose 没有等效的项目装饰概念。相反,您可以直接在组合中将任何 UI 装饰添加到列表中。例如,要向列表添加分隔线,您可以在每个项目后使用 Divider 可组合项

LazyColumn(Modifier.fillMaxSize()) {
    itemsIndexed(data) { index, d ->
        ListItem(d)
        if (index != data.size - 1) {
            Divider()
        }
    }
}

项目动画

可以将 ItemAnimator 设置在 RecyclerView 上以在对适配器进行更改时设置项目的出现动画。默认情况下,RecyclerView 使用 DefaultItemAnimator,它在删除、添加和移动事件上提供基本动画。

Lazy 列表通过 animateItemPlacement 修饰符具有类似的概念。请参阅 项目动画 以了解更多信息。

其他资源

有关将 RecyclerView 迁移到 Compose 的更多信息,请参阅以下资源