【问题标题】:RecyclerView SpanSizeLookup - HORRIBLE performance with a large data setRecyclerView SpanSizeLookup - 大型数据集的可怕性能
【发布时间】:2018-12-25 11:18:20
【问题描述】:

设置 - RecyclerView / GridLayoutManager / 自定义 SpanSizeLookup。没有什么不寻常的,它只是一个带有跨越整个宽度的标题的网格。

但是我注意到,随着适配器中的项目越来越多,性能会严重降低。我已经对此进行了分析,它是 100%,因为自定义查找中的 GetSpanSize。这是一个基本功能,但在滚动时似乎每帧上的每个项目都会调用它。果然,如果我拿出我的查找,无论我有多少项目,性能都很棒。作为一个用例,这可能是数千个项目。大约 1,000 个项目后,我开始发现性能问题。

从 Android 的角度来看,这听起来非常低效。我已经到处寻找有这个问题的其他人,但似乎找不到任何东西。

有什么想法吗?

谢谢,

编辑:添加了代码,但是即使我只返回 1 而不是进行实际查找,这种情况仍然会发生。这个问题似乎是每次滚动时列表移动时都会为适配器中的每个项目调用它。

public class SpanSizeLookup : GridLayoutManager.SpanSizeLookup
{
    //
    private GridLayoutManager LayoutManager;
    private MyItemAdapter ItemAdapter;
    //

    // SpanSizeLookup
    public SpanSizeLookup( GridLayoutManager layoutManager, MyItemAdapter itemAdapter )
    {
        LayoutManager = layoutManager;
        ItemAdapter = itemAdapter;
    }

    // GetSpanSize
    public override int GetSpanSize( int position )
    {
        switch ( ItemAdapter.GetItemViewType( position ) )
        {
            case TYPE_HEADER:
                return LayoutManager.SpanCount;
            case TYPE_ITEM:
                return 1;
        }

        return -1;
    }
}

// GetItemViewType
public override int GetItemViewType( int position )
{
    if ( ItemList[ position ].GUID.Equals( Guid.Empty ) )
        return TYPE_HEADER;

    return TYPE_ITEM;
}

【问题讨论】:

  • 请从 GetSpanSize 添加您的代码,以便我们为您提供帮助。很可能,您正在做一些需要很长时间才能在代码中完成的事情,一旦我们看到您在做什么,我们可以提供有关如何解决问题的建议。如果你做得对,适配器应该能够处理数千个项目。
  • 好吧,至少你知道是你的代码变慢了,所以它是可以修复的。只需缓存地图中项目的跨度大小。我已经通过简单的 switch / if-else 使用了跨度大小,并且从未遇到任何问题(是的,对于数千个项目),但我不明白列表大小如何影响这一点? RV 应该只为屏幕上可见的项目调用它。听起来像您的代码中的问题
  • 添加代码,谢谢。但是,每次滚动时它肯定会为每个 Item 调用 GetSpanSize,这就是为什么它会降低您拥有的 Item 越多。
  • 如果我只是添加一个 GridLayoutManager.DefaultSpanSizeLookup,一切正常。但是,即使我添加了一个只返回 1 的自定义查找,事情仍然很慢。这对我来说没有任何意义,因为默认实现只是返回 1 反正。有什么想法吗?
  • @Sourabh 那么你如何将缓存的跨度大小分配给每个位置?除了SpanSizeLookup,还有别的办法吗?我在一个包含 2k 多个项目的列表中的固定位置只有 4 个标题,但我仍然必须忍受所有这些口吃。急需一条出路!

标签: android android-recyclerview xamarin.android gridlayoutmanager


【解决方案1】:

问题是您还没有覆盖 GetSpanIndex。 DefaultSpanSizeLookup 本质上是这样的

public class DefaultSpanSizeLookup : GridLayoutManager.SpanSizeLookup
{
   public int GetSpanSize(int position) 
   {
      return 1;
   }

   public int GetSpanIndex(int position, int spanCount) 
   {
      return position % spanCount;
   }
}

如果您使用相同的值覆盖 GetSpanIndex,您将获得与使用 DefaultSpanSizeLookup 相同的性能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-20
    • 2018-12-14
    • 2019-06-29
    • 2018-03-18
    • 1970-01-01
    • 2018-01-27
    • 2012-05-25
    相关资源
    最近更新 更多