Как перенести RecyclerView в Lazy list

RecyclerView – это компонент View, который позволяет эффективно отображать большие наборы данных. Вместо того чтобы создавать представления для каждого элемента в наборе данных, RecyclerView повышает производительность приложения, поддерживая небольшой пул представлений и перерабатывая их при прокрутке элементов.

В Compose для этого можно использовать Lazy lists. На этой странице рассказывается, как перенести реализацию RecyclerView на ленивые списки в Compose.

Этапы переноса

Чтобы перенести реализацию RecyclerView в Compose, выполните следующие действия:

  1. Закомментируйте или удалите 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. Определите, какой тип Lazy list composable вам нужен, исходя из менеджера макета RecyclerView (см. таблицу ниже). Выбранная вами composable-функция станет composable-функцией верхнего уровня элемента ComposeView, добавленного на предыдущем шаге.

    LayoutManager

    Composable

    LinearLayoutManager

    LazyColumn или LazyRow

    GridLayoutManager

    LazyVerticalGrid или LazyHorizontalGrid

    StaggeredGridLayoutManager

    LazyVerticalStaggeredGrid или LazyHorizontalStaggeredGrid

    // 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 соответствующую composable-функцию. Каждый тип представления обычно сопоставляется с подклассом ViewHolder, но это не всегда так. Эти функции будут использоваться для представления разных типов элементов в списке:

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

    Логика методов onCreateViewHolder() и onBindViewHolder() в вашем RecyclerView.Adapter будет заменена на эти функции и состояние, которое вы им передадите. В Compose нет разделения между созданием composable-функции для элемента и привязкой к ней данных — эти концепции объединены.

  4. В слоте content списка Lazy (последний параметр лямбда-функции) используйте функцию items() (или эквивалентную перегрузку), чтобы перебрать данные для списка. В лямбда-функции itemContent вызовите подходящий составной элемент для ваших данных:

    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 нет аналога декоративных элементов. Вместо этого вы можете добавить любые элементы интерфейса в список прямо в композицию. Например, чтобы добавить разделители в список, можно использовать composable-функцию Divider после каждого элемента:

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

Анимация объектов

Атрибут ItemAnimator можно задать для элемента RecyclerView, чтобы анимировать появление элементов при изменении адаптера. По умолчанию RecyclerView использует DefaultItemAnimator, которая обеспечивает базовые анимации при удалении, добавлении и перемещении событий.

В ленивых списках используется похожая концепция, но с модификатором animateItemPlacement. Подробнее об анимации элементов…

Дополнительные ресурсы

Чтобы узнать больше о переносе RecyclerView в Compose, ознакомьтесь со следующими ресурсами: