【问题标题】:RecyclerView: how to clear cached/recycled views?RecyclerView:如何清除缓存/回收的视图?
【发布时间】:2015-01-14 20:05:18
【问题描述】:

我使用 RecyclerView 以列表布局显示项目列表。我从列表布局切换到网格布局,在网格布局中只显示所有数据的子集。此开关使用与显示列表布局时不同的布局 XML。

所有这一切都很好,除了当我滚动时,回收(缓存?)列表布局视图填充网格,与适当的网格布局视图项混合。换句话说,我没有在 RecyclerView 中为每个项目的布局使用我的 layout_grid.xml,而是使用 layout_list.xml 布局获取项目,但采用网格格式。

这告诉我 LayoutManager 工作正常,从列表切换到网格布局。但并非所有项目视图项目都使用网格 xml 布局重新创建,而是使用回收的列表布局视图。

我尝试了RecyclerView.removeAllViews()RecyclerView.removeAllViewInLayout()RecyclerView.swapAdapter()(强制适配器重新加载),但均无济于事。

更新:

如果我在列表中向下滚动两个位置,然后从列表切换到网格,前两个位置不会通过 onCreateViewHolder(),而是直接到 onBindViewHolder(),因此不会强制使用网格布局 xml .相反,前两个位置项被回收(我认为)并以其列表布局格式显示。

【问题讨论】:

    标签: android android-recyclerview


    【解决方案1】:

    使用

    recyclerView.getRecycledViewPool().clear();
    

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题。 Mann 建议的解决方案效果很好。另一种选择是将 RecyclerView 的 RecycledViewPool 设置为新实例。这也适用于我。

      recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
      

      但我认为覆盖 getItemViewType() 是更清洁的解决方案。

      【讨论】:

        【解决方案3】:

        听起来接受的答案是适合您情况的正确答案,返回不同的 viewType 可能是您需要做的。

        如果有人确实需要找到一种方法来清除缓存的视图持有者并最终出现在这个线程中,那么我发现这是可行的。

        您需要致电setLayoutManager(null)setAdapter(null)。如果你想保留你的适配器,你可以这样做adapter = getAdapter(); setAdapter(null); setAdapter(adapter);

        【讨论】:

        • 在我的情况下,设置layoutmanager(null) setAdapter(null) 对我有用。这让我免于拔头发!
        【解决方案4】:

        好的,现在我明白了。你使用这两种布局?有一种方法可以返回列表/网格元素(id/位置)的视图类型。您也必须正确实现此方法,以便适配器可以为新视图回收正确的布局。 你明白我的意思吗? :)

        【讨论】:

        • 我实现了一个 getItemViewType(int position) 来确定我是否有一个空视图。我应该在那里四处寻找以确定我正在处理的视图类型吗?
        • 是的。否则recyclerview没有机会知道要回收哪个viewtype
        • 好的,我明白你的意思了。但是我在哪里设置视图类型?对于列表或网格布局,它似乎返回 0。
        • 必须根据索引手动返回viewtype,然后在create方法/bindViewHolder方法中读取
        • 啊……我明白了。体力劳动。 :-) 我今晚要试一试(现在得跑了)。感谢您向我指出这一点。如果成功,我会在完成后标记答案。
        【解决方案5】:

        这里的关键是覆盖 getItemViewType(int position) 并设置它,以便我可以检查我正在为该位置处理的视图类型(列表或网格),然后在 @987654322 中为该位置设置适当的视图处理@。下面,viewFormat 只是一个 int,当用户点击菜单按钮更改格式时,我将其设置为列表或网格。

        @Override
            public int getItemViewType(int position) {
                if (listData.size() == 0) {
                    return EMPTY_VIEW;
                } else if (viewFormat == Constants.LIST_FORMATTED) {
                    return Constants.LIST_FORMATTED;
                } else if (viewFormat == Constants.GRID_CONDITION) {
                    return Constants.GRID_CONDITION;
                }
                return super.getItemViewType(position);
            }
        

        一位在我原来的帖子上发布 cmets 的用户让我意识到了这一点,但不幸的是,这些 cmets 已被删除。我感谢该用户为我指明了正确的方向。

        【讨论】:

          【解决方案6】:

          Recyclerview 具有视图缓存以及回收视图池(视图持有者池)。

          缓存是视图(具有填充数据的视图)。当 LayoutManager 告诉 recyclerview 视图不再可见且不再需要时,recyclerview 检查该视图是否对特定位置仍然有效,如果有效则将其添加到缓存中,因此当下次 LM 请求该位置的视图时,它会返回原样从缓存中获取。

          那么什么是回收视图池?当视图从缓存中删除或不再是有效视图时,与这些视图相关的数据将被清除,并且只有视图持有者对象保留在池中。根据 itemType,池可以有不同项目类型的视图持有者。

          现在,在您的情况下,您的视图对于该特定位置无效,因为您希望显示完全不同的视图。所以,你的适配器应该告诉 recyclerview 所有的视图都是无效的。唯一的方法是对所有项目使用 notifyDataSetChanged。 Recyclerview 将从缓存中删除视图并将其添加到回收器视图池中。所以现在,当 LM 请求视图时,要么返回回收的视图(根据 itemType),要么返回新创建的视图,然后适配器将数据绑定到这些视图。

          【讨论】:

            【解决方案7】:

            只要这样做 简单!!

            adapter.notifyItemRangeRemoved(0,adapter.getItemCount());
            
              adapter.notifyItemRangeRemoved(0,adapter.getItemCount());
                               for (int i = 0; i < array.length(); i++) {
                                    JSONObject object = array.getJSONObject(i);
                                     ////
                                    data_List.add(data);
                                }
            

            【讨论】:

              【解决方案8】:
              final int targetCacheSize = 2;
                  recyclerView.setItemViewCacheSize(Integer.MIN_VALUE);
                  recyclerView.getRecycledViewPool().clear();
                  recyclerView.setItemViewCacheSize(targetCacheSize);
              

              【讨论】:

              • 欢迎来到 Stack Overflow。您能否为您的代码添加一些解释以及它如何回答问题?
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-11-02
              • 1970-01-01
              • 2015-05-23
              • 2015-11-24
              • 2013-10-01
              • 2011-02-22
              相关资源
              最近更新 更多