← Назад к вопросам

Что такое RecycledViewPool?

2.0 Middle🔥 132 комментариев
#UI и вёрстка#Производительность и оптимизация

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое RecycledViewPool?

RecycledViewPool — это ключевой механизм в архитектуре RecyclerView для эффективного повторного использования ViewHolder'ов между несколькими RecyclerView (или внутри одного, но с разными типами элементов). Его основная цель — минимизировать затраты на создание (inflate) и привязку (bind) новых ViewHolder'ов, что напрямую повышает производительность и плавность прокрутки, особенно в сложных интерфейсах.

Проще говоря, это общий "пул" или кэш, где хранятся "освобождённые" (откреплённые от данных) ViewHolder'ы. Когда RecyclerView нуждается в новом ViewHolder'е для отображения элемента на экране, он сначала проверяет пул на наличие подходящего кандидата, прежде чем создавать его с нуля.

Как работает RecycledViewPool?

Каждый RecyclerView имеет свой собственный RecycledViewPool по умолчанию. Однако его мощь раскрывается, когда мы делим один пул между несколькими RecyclerView.

Основной принцип работы:

  1. Сбор "мусора": Когда элемент прокручивается за пределы экрана (off-screen), его ViewHolder не уничтожается, а "скрапится" (очищается от данных) и помещается в пул.
  2. Классификация по типам: Пул организует ViewHolder'ы по типам представления (view type). Каждый тип соответствует своему layoutId (например, заголовок, обычный элемент, рекламный блок).
  3. Извлечение из пула: Когда нужно показать новый элемент, RecyclerView запрашивает у пула ViewHolder заданного типа. Если таковой есть — он извлекается и используется повторно. Если нет — создаётся новый.

Ключевые параметры пула:

Пул имеет настройки для каждого типа ViewHolder:

  • Максимальное количество хранимых экземпляров (setMaxRecycledViews()). По умолчанию — 5. Это предотвращает неограниченный рост пула.
// Установка общего пула для двух RecyclerView
val sharedPool = RecyclerView.RecycledViewPool()
recyclerView1.setRecycledViewPool(sharedPool)
recyclerView2.setRecycledViewPool(sharedPool)

// Настройка максимального количества ViewHolder'ов для типа 0
sharedPool.setMaxRecycledViews(0, 15)

Зачем использовать общий RecycledViewPool?

Основная выгода проявляется в сценариях с несколькими независимыми RecyclerView на одном экране (например, горизонтальные списки внутри вертикального, как в Netflix или Google Play).

Без общего пула:

  • Каждый RecyclerView имеет изолированный кэш.
  • При переходе между вкладками или скролле, если один список уже создал ViewHolder'ы типа "А", а второй список того же типа только начинает прокрутку — он будет создавать их заново, несмотря на то, что первый список мог их уже "выбросить".

С общим пулом:

  • ViewHolder'ы, освобождённые первым списком, попадают в общий пул.
  • Второй список может сразу взять их оттуда, избежав дорогостоящего создания.
  • Результат: Снижение потребления памяти, уменьшение лаг-пиков при начале прокрутки и общее ускорение отзывчивости UI.

Отличие от других механизмов кэширования RecyclerView

Важно не путать RecycledViewPool с двумя другими уровнями кэша внутри RecyclerView.LayoutManager:

  1. Scrap (mAttachedScrap, mChangedScrap) — кратковременное хранение ViewHolder'ов, которые находятся в пределах компоновки (layout pass) и могут быть немедленно повторно привязаны к тем же позициям (например, при анимации или незначительном обновлении). Не связан с пулом.
  2. Cache (mCachedViews) — хранит небольшое количество (по умолчанию 2) недавно вышедших из виду ViewHolder'ов с ещё привязанными данными. Это позволяет мгновенно вернуть их на экран при обратном скролле без повторной привязки (bind). Когда этот кэш переполняется, самые старые ViewHolder'ы "скарапятся" и отправляются именно в RecycledViewPool.
// Упрощённая схема жизненного цикла ViewHolder
Новый элемент входит на экран (on-screen)
        ↑
    Создать новый? ←--- НЕТ --- Проверить mCachedViews? (быстрый возврат)
        |                             |
        ДА                           ДА (ViewHolder с данными)
        |                             |
    Проверить RecycledViewPool? ---→ Взять из пула, вызвать onBindViewHolder()
        |
        ДА
        |
    Взять из пула, вызвать onBindViewHolder()
        |
        НЕТ
        |
    onCreateViewHolder() → onBindViewHolder()

Практический пример использования

Представьте экран с двумя горизонтальными RecyclerView: один показывает фильмы, другой — сериалы. Но оба используют одинаковый макет для элемента (например, постер и название).

class MainActivity : AppCompatActivity() {

    private lateinit var moviesRecyclerView: RecyclerView
    private lateinit var seriesRecyclerView: RecyclerView
    private val sharedViewPool = RecyclerView.RecycledViewPool()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        moviesRecyclerView = findViewById(R.id.rv_movies)
        seriesRecyclerView = findViewById(R.id.rv_series)

        // Настраиваем оба адаптера с одинаковым типом элемента
        moviesRecyclerView.adapter = MediaAdapter(getMoviesList(), sharedViewPool)
        seriesRecyclerView.adapter = MediaAdapter(getSeriesList(), sharedViewPool)

        // Устанавливаем ОДИН И ТОТ ЖЕ пул для обоих списков
        moviesRecyclerView.setRecycledViewPool(sharedViewPool)
        seriesRecyclerView.setRecycledViewPool(sharedViewPool)

        // Можно увеличить лимит хранения, если элементов много
        sharedViewPool.setMaxRecycledViews(MediaAdapter.VIEW_TYPE_ITEM, 20)
    }
}

class MediaAdapter(private val items: List<MediaItem>, private val sharedPool: RecyclerView.RecycledViewPool) : RecyclerView.Adapter<MediaViewHolder>() {

    companion object {
        const val VIEW_TYPE_ITEM = 0
    }

    // ... onCreateViewHolder, onBindViewHolder, getItemCount ...

    override fun getItemViewType(position: Int): Int {
        return VIEW_TYPE_ITEM
    }
}

Итог: RecycledViewPool — это интеллектуальная система рециркуляции ViewHolder'ов, фундаментальная для производительности RecyclerView. Его явное использование для обмена ViewHolder'ами между несколькими списками является продвинутой, но крайне эффективной оптимизацией, позволяющей добиться максимальной плавности интерфейса в сложных компоновках.

Что такое RecycledViewPool? | PrepBro