使用GridLayoutManager和多个项目类型(具有不同的高度)滚动RecyclerView时发生滞后

时间:2018-08-08 12:30:20

标签: android android-recyclerview gridlayoutmanager

我已经使用RecyclerViewGridLayoutManager实现了adpter,其中包含具有不同高度的不同viewholders的多种商品类型。

不幸的是,RecyclerView在滚动时滞后。我观察到了这种行为:

  • 在特定的低端设备(平板电脑)上,该设备处于非常差的状态,并且总体来说速度很慢,当我上下滚动时,我会发现很多滞后。
  • 在高端设备(三星Galaxy S8)上,我看到从顶部开始的第一次滑动(滚动)始终存在滞后(无例外)

我认为不同的高度是造成此问题的原因,并且我尝试了许多不同的方法。其中包括:

  • 手动设置每个项目的高度(因此,没有wrap_content表示高度!)
  • 设置setHasStableIds(true)并在适配器中实现:

      

    重写fun getItemId(position:Int):长{       返回position.toLong()}

  • onBindViewHolder中什么都不做,仅依赖于xml布局中定义的视图持有者中的静态内容

  • 删除xml布局中与可绘制对象,其他图形和字体有关的所有内容。因此只剩下文本和基本布局,例如LinearLayout(等)。
  • 许多其他小的调整。.

我将尝试为您提供代码的相关部分。

因此,首先,这是我屏幕上带有recyclerview的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
            }
        }
    }

还有一个标题查看器的示例,它使用跨度来完全覆盖列表中的宽度:

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 个答案:

没有答案