У вас есть большой список данных для показа пользователям вашего приложения? Ищете гибкий, удобный для разработчиков и пользователей способ отображения данных?
Тогда 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
.
Читайте также:
- Последовательное объединение адаптеров с помощью MergeAdapter
- Отображение превью камеры с помощью PreviewView
- Распространенные и нелепые ошибки разработчиков Android-приложений
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Hrithik Sharma: Implement RecyclerView in android with kotlin