Оптимизация прокрутки вложенных в друг друга RecyclerView

Теги: Java, Android, RecyclerView

Заметка основана на статье Ninad MG “Optimizing Nested RecyclerView”.

RecyclerView обеспечивает плавную прокрутку списка путем помещения ViewHolder’ов ушедших за пределы экрана элементов в так называемый пул (Pool). Далее, при появлении новых элементов, RecyclerView не создает их заново, но использует ViewHolder’ы из пула, надувая (inflate) их актуальными данными. Таким образом достигается переиспользованиe ViewHolder’а и повышается производетельность фреймворка.

NB: для более полной картины проблемы производительности в RecyclerView см. раздел “Жизнь и смерть ViewHolder’а” в данной заметке. + раздел “Bonus” в этой заметке.

Итак, иногда, для создания некоторых макетов, нам необходимо вкладывать один RecyclerView в другой. Рассмотрим случай, когда горизонтальные RecyclerView вложены в вертикальный.

Когда вы прокручивавете вложенные горизонтальные списки то прокрутка будет плавной, но если прокручивать вертикальный список - прокрутка может притормаживать. Это происходит от того, что у каждого RecyclerView свой пул ViewHolder’ов. И каждый раз, при прокрутке вертикального списка, горизонтальные будут заново создавать свои ViewHolder’ы.

Мы можем исправить эту ситуацию, разделив между всеми RecyclerView один пул ViewHolder’ов.

Это делается с помощью функции RecyclerView.setRecycledViewPool(RecycledViewPool):

Теперь, когда у всех вложенных RecyclerView один пул ViewHolder’ов, они используют ViewHolder’ы друг друга, и прокрутка становится более плавной.

Но прокрутку можно оптимизировать еще больше.

Во-первых, конкретному типу View, можно задать максимальное количество ViewHolder’ов, которые будут хранится в пуле:

Таким образом, мы можем подкорректировать (т.е. увеличить) максимальные значения количества в пуле тех ViewHolder’ов, которых в каждый момент на экране больше, учитывая тот факт, что по умолчанию это количество равно пяти.

Во-вторых, начиная с support library 25.1.0 у нас есть возможность указать layoutManager’ам внутренних RecyclerView сколько View нужно подготовить перед появлением на экране:

где N - это количество видимых View.

Таким образом, если на экране внутренние горизонтальные списки за раз показывают минимум три с половиной View, мы можем написать так:

NB: По-умолчанию данное N = 2

Это позволяет внутренним RecyclerView создавать свои View на ранней стадии, что повышает производительность при прокрутке внешнего списка.

18 11 2017

Теги заметки: