【问题标题】:Am I breaking the performance and use of a recycler view?我是否破坏了回收者视图的性能和使用?
【发布时间】:2018-10-17 19:00:30
【问题描述】:

因此,当我们想要显示大量元素时,我们应该使用回收器视图。
这样做的好处是可以重复使用视图,因此我们不会膨胀列表中的每个视图并将它们保存在内存中,而只是将屏幕中显示的视图保存在内存中,以回收其余部分。
但是,如果回收的视图本身就是一个“迷你”列表呢?
IE。对于每个回收的项目,我们会通过删除所有子视图并添加新的子视图来更改其结构?
这是否违背了使用回收列表的整个想法?
有问题的示例(itemInRecycler 是一个垂直的LinearLayout,它被传递给回收站视图持有者):

itemInRecycler.removeAllViews();  
for(element: elements) {  
   CustomView view = inflate();  
   view.setDisplayData(element);  
   itemInRecycler.addView(view);  
} 

【问题讨论】:

    标签: android android-layout android-activity android-recyclerview android-linearlayout


    【解决方案1】:

    这是否违背了使用回收列表的整个想法?

    这取决于子列表在整个itemView 中有多少。如果子列表是您要显示的唯一内容,那么是的,您正在挫败很大一部分性能提升。每次绑定 ViewHolder 时,您仍然在膨胀视图,这是您在使用 RecyclerView 时尽量避免的事情之一。

    这还取决于子列表的大小。如果最多只有三个元素,那么成本就会降低。如果子列表是数百个项目,那么成本就很大。

    一种选择是使用 sub-RecyclerView 而不是 LinearLayout,并将每个 sub-RecyclerView 连接到相同的shared RecycledViewPool。通过这种方式,您可以获得 RecyclerView 与可滚动的 LinearLayout 的所有优点,但更好的是,因为每个子 RecyclerView 都可以从其他子 RecyclerView 获取 ViewHolders。

    如果这对您来说有点过于苛刻,您可以只优化您已经编写的代码。您可以重复使用现有视图(如果不够,只创建新视图),而不是每次清除列表然后重新增加正确数量的视图,如果有太多视图,则删除额外的视图。

    int i = 0;
    
    // reuse existing views
    for (; i < elements.size() && i < itemInRecycler.getChildCount(); i++) {
        Element element = elements.get(i);
        CustomView view = (CustomView) itemInRecycler.getChildAt(i);
        view.setDisplayData(element);
    }
    
    // create new views if there weren't enough to reuse
    for (; i < elements.size(); i++) {
        Element element = elements.get(i);
        CustomView view = inflate();
        view.setDisplayData(element);
        itemInRecycler.addView(view);
    }
    
    // remove any extras after we've reused everything
    int viewsToRemove = itemInRecycler.getChildCount() - i;
    
    if (viewsToRemove > 0) {
        itemInRecycler.removeViews(i, viewsToRemove);
    }
    

    elements 集合总是有 5 到 7 个元素的世界中,例如,这种方法将确保您始终重复使用前五个 CustomViews,然后仅膨胀或删除 0 -2 额外的CustomViews。

    【讨论】:

    • 这组for 循环基于Parcel.readTypedList() 的Android 实现,它同样重用现有列表,只是根据需要增加或缩小其大小:android.googlesource.com/platform/frameworks/base/+/27f592d/…跨度>
    • 感谢您的解释。你是对的,这个“子列表”是每个项目显示的大部分内容。现在元素不超过 4 个,但这意味着如果加载更多数据,解决方案将无法扩展。 1)您能否分享一些关于您提到的子回收器视图的代码,因为我不明白这是如何完成的? 2)如果我理解正确,保留一些孩子并删除额外的孩子的方法,反之亦然,对于具有不同项目的列表也不会扩展,例如具有 2 个子列表的项目和具有 20 个子列表的项目?也不会针对包含大量数据的列表进行扩展?
    • Re (2):绑定 ViewHolders 时要避免的“成本”主要是膨胀视图的成本,还有一点是使用 findViewByid() 进行视图查找的成本。我提到的“重用你可以使用的视图”方法试图降低膨胀视图的成本,但是是的,它有点有限。如果你的一半视图持有者有两个项目,一半有 20 个,你会发现自己经常夸大 18 个视图。但是如果一半有 100 次浏览,一半有 101 次浏览,那么你会发现你只增加了一个浏览量,这还不错。
    • Re (1):我认为这有点超出了答案的范围(它更像是一篇博客文章)。但基本上这些步骤是... 一:您将创建一个RecycledViewPool。第二:在onCreateViewHolder() 中,你会膨胀一个持有RecyclerView 而不是LinearLayout 的视图,然后你会调用setRecycledViewPool(sharedPool)。三:在onCreateViewHolder() 中为您的 RecyclerView 设置一个Adapter 以使用Element 对象。四:在onBindViewHolder()中设置Adapter的元素并调用notifyDataSetChanged()
    • 有点轻,不过这篇博文讲了一点:proandroiddev.com/optimizing-nested-recyclerview-a9b7830a4ba7
    猜你喜欢
    • 2021-04-29
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 2015-12-07
    • 2010-11-09
    • 2011-04-15
    • 1970-01-01
    相关资源
    最近更新 更多