Оптимизация прокрутки вложенных в друг друга 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 на ранней стадии, что повышает производительность при прокрутке внешнего списка.