Короткая история: У меня есть (предварительное кэширование) Custom LinearLayoutManager
, RecyclerView
, Custom RecyclerView.Adaptor
, Custom RecyclerView.ViewHolder
setup.У меня есть только один viewType и облегченные функции привязки.Это действительно ничего особенного, поэтому я надеюсь, что мне не нужно размещать код.Я также не хочу путать со всем нерелевантным кодом.
Проблема, с которой я столкнулся, заключается в том, что, несмотря на то, что не удается перезапустить какие-либо представления, onCreateViewHolder по-прежнему вызывается время от времени (после начальных раздуваний строк), что заставляет меня задуматься о том, чтоможет у меня утечка памяти?Как вы думаете, это так и почему?Что решает, что моему приложению все еще нужно создавать больше представлений, а не перерабатывать?
Я добавлю одну вещь, которая может как-то учитываться.Мои строки имеют два визуальных состояния (они расширяются и сворачиваются), и кажется, что наличие более случайного сочетания строк в разных состояниях усугубляет проблему.
Полная история: Я заметил случайный сбой в плавной прокрутке моего RecyclerView
.Используя профилировщик android studio, я заметил следующее:
- Все мои
bindViewHolder
методы достаточно быстрые и не сдерживают прокрутку. OnCreateViewHolder
- вот что вызываетзаиканиеЭто объясняет, почему во время первой прокрутки всегда есть несколько заиканий.Более того, это инфляция, которая занимает смехотворно высокий процент времени процессора. - С разметкой элемента / строки, построенной с использованием
ConstraintLayout
, низкая производительность функций onMeasure
снизила производительность прокрутки на более слабых устройствах.. - При компоновке элемента / строки, построенной с использованием
LinearLayout
s, производительность значительно улучшилась.Однако раздувание представлений по-прежнему занимает достаточно много времени, чтобы вызвать всплески.
С этой информацией я максимально упростил макет элемента строки, убедившись, что он использует LinearLayout
s.Несмотря на это, рендеринг элементов в окне повторного просмотра не должен приводить к заиканию после появления первых элементов на экране, поскольку, во-первых, строки одинаковы, за исключением данных, связанных с ними, и двух, RecyclerView
должен перерабатывать строки.Таким образом, onCreateViewHolder
следует сначала назвать много, а затем редко.Как насчет предварительного кэширования?Я обнаружил, что это одна из причин, по которой при прокрутке запрашиваются новые пользователи.Я установил кэш и создал пользовательский LinearLayoutManager
, который переопределяет метод предварительного кэширования (pre-fetching?), Называемый getExtraLayoutSpace(RecyclerView.State state)
, и настроил их так, чтобы было достаточно существующих перерабатываемых представлений для покрытия запроса во время прокрутки.Мои тесты подтверждают, что после начальной прокрутки новые виды не запрашиваются при переходе в состояние прокрутки.
Все это и у меня осталось две проблемы.Одним из них является то, что onCreateViewHolder
вызывается очень часто во время использования приложения, и это вызывает небольшой сбой.Я поместил Log.w()
внутри onFailedToRecycleView()
, чтобы увидеть, что любые виды не перерабатываются, и похоже, что виды перерабатываются.Так что теперь я думаю, что есть некоторая утечка памяти, и профилировщик памяти показывает скачки в использовании памяти, часто происходящие, когда вызывается onCreateViewHolder
.