Задержка при прокрутке 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), Неважно, какой из моих типов предметов я использую, если они имеют одинаковую высоту на всем пути вниз.

Но это не вариант в моем случае, так как мне нужно, чтобы элементы имели разную высоту для моих индивидуальных элементов.

0 ответов

Другие вопросы по тегам