Задержка при прокрутке RecyclerView с помощью GridLayoutManager и нескольких типов элементов (с разной высотой)
Я реализовал RecyclerView
с использованием GridLayoutManager
и adpter
, содержащий несколько типов элементов с разными viewholders
разной высоты.
К сожалению, RecyclerView
отстает при прокрутке. Я наблюдал это поведение:
- На конкретном низкоуровневом устройстве (планшете), который находится в очень плохом состоянии и действительно очень медленный в целом, я мог видеть много задержек при прокрутке вверх и вниз.
- На высококлассном устройстве (Samsung Galaxy S8), я вижу задержку при первом пролистывании (прокрутка) сверху последовательно (без исключений)
Я думаю, что разные высоты являются причиной этой проблемы, и я пробовал много разных подходов. Среди них:
- установка высоты каждого элемента вручную (так что нет wrap_content для высоты!)
Установка setHasStableIds(true) и реализация этого в адаптере:
переопределить веселье getItemId(position: Int): Long { return position.toLong() }
Во время ничего в
onBindViewHolder
и полагаться только на статический контент в видоискателях, определенных в макетах xml- Удаление всего, что связано с рисованными объектами, другой графикой и шрифтами в макетах XML. Так что только текст и основные макеты, как
LinearLayout
(и т. д.) был оставлен. - Много других мелких корректировок..
Я постараюсь дать вам соответствующие части моего кода.
Итак, во-первых, вот xml моего экрана с изображением реселлера:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/customersRecyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="50dp"
android:paddingBottom="50dp"
android:layout_weight="1"
android:clipToPadding="false">
</android.support.v7.widget.RecyclerView>
</FrameLayout>
А вот код для создания адаптера:
var columns = if (isBigScreen && isLandscape) 6
else if (isBigScreen) 5
else if (isLandscape) 4
else 3
val gridLayoutManager = GridLayoutManager(context, columns, GridLayoutManager.VERTICAL, false)
mCustomersRecyclerview?.layoutManager = gridLayoutManager
mCustomersAdapter = CustomersAdapter(customersListItems, gridLayoutManager, columns)
mCustomersRecyclerview?.adapter = mCustomersAdapter
И конструктор адаптера:
constructor(items: ArrayList<ListItem> = ArrayList(), layoutManager: GridLayoutManager, spanSize: Int) {
mItems = items
mSpanSize = spanSize
mLayoutManager = layoutManager
setHasStableIds(true)
mLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
when (getItemViewType(position)) {
ItemType.HEADLINE_PRIMARY.index,
ItemType.HEADLINE_SECONDARY.index -> {
return spanSize
}
}
return 1
}
}
}
И пример держателя заголовка, который использует span, чтобы полностью покрыть ширину в списке:
Часть onCreateViewHolder (...)
when (viewType) {
ItemType.HEADLINE_PRIMARY.index -> {
layoutView = prepareViewHolder(parent, R.layout.customers_list_item_headline_primary, false)
if (layoutView != null) {
viewholder = HeadlinePrimaryViewHolder(layoutView)
}
}
И onBindViewHolder (...)
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = mItems.get(position)
if (holder is HeadlinePrimaryViewHolder && item is HeadlinePrimaryListItem) {
holder.bind(item)
И сам зритель
class HeadlinePrimaryViewHolder: RecyclerView.ViewHolder {
private var mCustomersPrimaryHeadline: MTTextView? = null
constructor(view: View?) : super(view) {
mCustomersPrimaryHeadline = view as MTTextView
}
fun bind(itemPrimary: HeadlinePrimaryListItem) {
var headline: String = itemPrimary.headline
mCustomersPrimaryHeadline?.setText(headline)
}
}
(XML этого видоискателя - простое текстовое представление и ничего более)
Прокручивается плавно, когда..
Другие видоискатели, кроме заголовков, используют только 1 столбец (1 интервал) и выглядят по-разному и имеют разные высоты, как упоминалось ранее.
Единственное, что положительно повлияло на производительность, - это использование одинаковых элементов / представлений или, по крайней мере, элементов с одинаковой высотой для всего списка. Как с настройкой, так и без setHasFixedSize(true)
, Неважно, какой из моих типов предметов я использую, если они имеют одинаковую высоту на всем пути вниз.
Но это не вариант в моем случае, так как мне нужно, чтобы элементы имели разную высоту для моих индивидуальных элементов.