Kotlin-реализация RecyclerView на Android

У вас есть большой список данных для показа пользователям вашего приложения? Ищете гибкий, удобный для разработчиков и пользователей способ отображения данных?

Тогда RecyclerView  —  именно то, что вам нужно.

RecyclerView  —  это расширенная версия ListView, только более мощная и гибкая.

RecyclerView относится к семейству ViewGroup, которое является оптимизированным преемником ListView и GridView.

Как следует из названия, RecyclerView перезапускает верхние элементы списка, которые, уходя за пределы с экрана, становятся невидимыми для пользователя. Например, если пользователь прокрутит список вниз до пункта 6 или 7, то элементы в позиции 1, 2 или 3 будут удалены из памяти. В результате сокращается расход памяти.


Предварительные условия:

  • Базовые знания xml и kotlin;
  • Свободное обращение с классами и объектами;
  • Навыки использования ViewBinding.

Компоненты, необходимые для настройки RecyclerView:

  • Модель  —  для доступа к данным, которые должны быть показаны пользователю.
  • XML-шаблон — для отображения данных пользователю.
  • Adapter (Адаптер)  —  для привязки данных к RecyclerView.
  • ViewHolder — для получения ссылки на View-элементы, которые должны быть динамически изменены во время выполнения программы.

Пошаговое погружение в процесс написания кода

Создание нового проекта:

  • Перейдите в раздел File > New > New Project.
  • Выберите Empty Activity и нажмите кнопку Next.
  • Дайте проекту подходящее имя и введите имя пакета (или оставьте его по умолчанию).
  • Выберите Kotlin в качестве языка и минимальный SDK-пакет (получить помощь можно по ссылке Help me choose.
  • Нажмите кнопку Finish.
  • Дождитесь, когда появится главное окно Android Studio.

Создание Model

  • Создайте новый класс Kotlin
    • Щелкните правой кнопкой мыши на пакет в окне проекта.
    • Выберите New>Kotlin Class/File.
    • Выберите Data Class из параметров типа класс.
    • Введите имя FoodItem и нажмите Enter.
  • Не беспокойтесь об ошибке в скобках класса данных.
  • Заполните поля (укажите наименование и цену продуктов) для своей модели.

Код для нашего класса моделей такой:

data class FoodItem(val name:String, val price:Float)

Создание XML-шаблона для элементов

  • Щелкните правой кнопкой мыши res/layout и выберите New>Layout Resource File.
  • Присвойте файлу имя food_item_layout и нажмите кнопку ОК.
  • Скопируйте и вставьте этот код в файл:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#0000FF"
android:layout_margin="6dp"
xmlns:app="http://schemas.android.com/apk/res-auto">

<TextView
android:id="@+id/foodItemNameTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#FFF"
android:text="Food Item 1"
android:layout_margin="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>

<TextView
android:id="@+id/foodItemPriceTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFF"
android:text="Rs. 200"
android:layout_marginEnd="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/foodItemNameTV"
app:layout_constraintBottom_toBottomOf="@id/foodItemNameTV"/>

</androidx.constraintlayout.widget.ConstraintLayout>
  • В activity_main.xml добавьте этот код, чтобы установить шаблон для RecyclerView в MainActivity:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/foodItemsRV"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Инициализация ViewBinding

  • Откройте файл уровня build.gradle.
  • В разделе android добавьте этот код:
buildFeatures{     
viewBinding true
}
  • Нажмите Sync Now и дождитесь завершения процесса сборки.

Настройка Adapter для RecyclerView

Чтобы обеспечить привязку ваших данных к элементам списка, выполните следующие действия:

  • Сначала создайте новый класс Kotlin и назовите его FoodItemAdapter с параметрами Contextи MutableList<FoodItem>
  • Затем создайте внутренний класс FoodItemViewHolder— ViewHolder для RecyclerView.
  • Запишите код для внутреннего класса:
class FoodItemViewHolder(foodItemLayoutBinding: FoodItemLayoutBinding)
: RecyclerView.ViewHolder(foodItemLayoutBinding.root){

}
  • Расширьте FoodItemAdapterс помощью RecyclerView.Adapter<FoodItemAdapter.FoodItemViewHolder>()
  • Наведите курсор на ошибку в классе адаптера, нажмите Alt+Enter и выберите Implement members, чтобы реализовать элементы базового класса адаптера.
  • Когда откроется окно, выберите все элементы из списка и нажмите кнопку ОК.

Элемент-функции:

onCreateViewHolder()— метод для создания ViewHolder.

onBindViewHolder() — метод для привязки данных к элементам списка.

getItemCount() — метод для определения количества элементов, которые надо отобразить.

  • Добавьте этот код в onCreateViewHolder:
val binding = FoodItemLayoutBinding.inflate(LayoutInflater.from(context),parent,false)
return FoodItemViewHolder(binding)
  • Создайте функцию bind(foodItem: FoodItem) в FoodItemViewHolder и привяжите данные к элементам списка.
  • Вот код:
private val binding = foodItemLayoutBinding

fun bind(foodItem: FoodItem){
binding.foodItemNameTV.text = foodItem.name
binding.foodItemPriceTV.text = "Rs. ${foodItem.price}"
}
  • Теперь добавьте в элемент-функцию onBindViewHolder этот код:
val foodItem = foodItemList[position]
holder.bind(foodItem)
  • В getItemCount просто добавьте строку return foodItemList.size

Вот полный код для адаптера:

class FoodItemAdapter(private val context: Context, private val foodItemList:MutableList<FoodItem>)
: RecyclerView.Adapter<FoodItemAdapter.FoodItemViewHolder>() {


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FoodItemViewHolder {
val binding = FoodItemLayoutBinding.inflate(LayoutInflater.from(context),parent,false)
return FoodItemViewHolder(binding)
}

override fun onBindViewHolder(holder: FoodItemViewHolder, position: Int) {
val foodItem = foodItemList[position]
holder.bind(foodItem)
}

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


class FoodItemViewHolder(foodItemLayoutBinding: FoodItemLayoutBinding)
: RecyclerView.ViewHolder(foodItemLayoutBinding.root){

private val binding = foodItemLayoutBinding

fun bind(foodItem: FoodItem){
binding.foodItemNameTV.text = foodItem.name
binding.foodItemPriceTV.text = "Rs. ${foodItem.price}"
}

}
}

Инициализация адаптера в классе MainActivity

1. Заполните список продуктов питания, которые будут отображаться в окне RecyclerView:

  • Создайте свойство foodItemsList как MutableList<FoodItem> и инициализируйте список.
  • Создайте функцию populateList() и вызовите ее в onCreate() класса activity после setContentView().
  • Добавьте в функцию этот код:
for (i in 1..15){
val name = "Food Item $i"
val price = (100 * i).toFloat()

val foodItem = FoodItem(name = name, price = price)

foodItemsList.add(foodItem)
}

2. Инициализируйте адаптер и менеджер разбивки:

  • Создайте свойство adapter как FoodItemAdapter и сделайте его lateinit.
  • Создайте функцию setUpAdapter() и вызовите ее после populateList().
  • Добавьте в эту функцию код:
adapter = FoodItemAdapter(this,foodItemsList)
b.foodItemsRV.adapter = adapter
b.foodItemsRV.layoutManager = LinearLayoutManager(this)
  • Поскольку размещение элементов в RecyclerView по умолчанию вертикальное, можете изменить его на горизонтальное с помощью опции:
b.foodItemsRV.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
  • Если хотите добавить разделительную линию между view-элементами, воспользуйтесь опцией:
b.foodItemsRV.addItemDecoration(DividerItemDecoration(this,DividerItemDecoration.VERTICAL))

Совет: чтобы добавить, удалить или отредактировать элементы из данных, выполните следующие действия:

  • Сначала обновите foodItemsList, а затем уведомите адаптер об изменении, внесенном вами в список в определенной позиции.

Для удаления элемента:

В списке  —  foodItemList.removeAt(position)

Уведомление адаптеру  —  notifyItemRemoved(position)

Для добавления элемента:

В списке  —  foodItemList.add(position, foodItem)

Уведомление адаптеру  —  notifyItemInserted(position)

Для редактирования элемента:

В списке  —  сначала удалите элемент foodItemList.removeAt(position), затем добавьте новый элемент foodItemList.add(position,newFoodItem)

Уведомление адаптеру  —  notifyItemChanged(position)

Примечание: чтобы уведомить адаптер за пределами класса адаптера, используйте экземпляр адаптера  —  adapter.notifyItemInserted(position)


Пришло время запустить приложение. Не знаете, как запустить приложение? Посмотрите документацию.

Исходный код приложения доступен на github.

В RecyclerView есть гораздо больше возможностей, чем описано в этой статье. Но с помощью нашего краткого обзора вы сможете легко создать свой собственный пользовательский RecyclerView.

Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Hrithik Sharma: Implement RecyclerView in android with kotlin

Предыдущая статьяСоздание приложения Flask на Python для визуализации мест путешествий
Следующая статьяТоп-10 книг для Java-программистов