【问题标题】:I want my RecyclerView to not recycle some items我希望我的 RecyclerView 不回收某些物品
【发布时间】:2016-03-30 15:19:15
【问题描述】:

我正在使用内部具有异构视图的RecyclerView as seen in this tutorial

我在 RecyclerView 中有一些项目也是 RecyclerViews。太难以想象?假设我想复制 Play 商店的布局:一个具有垂直线性布局并由许多元素填充的大型 RecyclerView:单个应用程序和应用程序轮播。

如果要添加的项目是单个应用程序的布局,则将使用 ID 1,我将为单个项目添加布局。 否则,如果我需要添加轮播,那么我将向主 RecyclerView 添加一个元素:另一个带有自己的适配器的 RecyclerView。

效果很好。除非您滚动主 RecyclerView。为什么?因为某些视图在不再可见时被销毁,然后在 onBindViewHolder() 方法中重新创建。为什么在这里?因为主RecyclerView的Adapter是传给位置X,然后调用OnBindViewHolder()。然后后者使用自己的适配器创建一个新的 RecyclerView 并将其分配给它。我想保留这些观点,因为它们每次都需要重新膨胀。

这可能吗?如果是的话,你能告诉我怎么做吗?

【问题讨论】:

    标签: android android-layout android-recyclerview


    【解决方案1】:

    使用这个:

    recyclerView.getRecycledViewPool().setMaxRecycledViews(TYPE_CAROUSEL, 0);
    

    这不会回收 viewType TYPE_CAROUSEL 的任何视图,但如果该类型的项目数非常高,那么它会显着降低您的性能,甚至可能导致 OOMEs

    编辑

    阅读MML13的回答后,我认为它可能对你有用。当视图在外部 RecyclerView 中重新绑定时,您担心轮播的项目会重新膨胀。如果所有这些轮播都属于同一类型,即它们都使用相同的适配器,您可以将适配器保留在外部 RecyclerView 的 ViewHolder 中,并在重新绑定时交换数据并在此适配器上调用 notifyDataSetChanged()notifyItemRangeChanged(...)。这将回收所有轮播视图以及这些轮播中的所有视图。

    【讨论】:

    • int viewType 参数要传递的默认值是多少?我找不到任何文档?
    • @Sanoop 除非您覆盖 getItemViewType,否则默认 viewType 为 0(请参阅 this
    • 非常感谢,伙计.. 你确实救了我的头:) :) +1
    • 如何在适配器中声明 TYPE_CAROUSEL?你有初始化和赋值等的例子吗
    【解决方案2】:

    您也可以在适配器的 onBindViewholder() 方法中设置以下代码。

    holder.setIsRecyclable(false);
    

    我参考了这个链接

    http://aphoe.com/blog/prevent-androids-recyclerview-recycling-views/

    【讨论】:

      【解决方案3】:

      您可以添加您的适配器:

      @Override
      public void onBindViewHolder(final CommentViewHolder viewHolder, final int position) {
          viewHolder.setIsRecyclable(false);
      }
      

      通知回收者该项目是否可以回收。在 setIsRecyclable() 稍后设置为 true 之前,不可回收的视图不会被其他项目重用。对setIsRecyclable() 的调用应始终配对(对setIsRecyclabe(false) 的一次调用应始终与对setIsRecyclable(true) 的稍后调用相匹配)。由于状态是内部引用计数的,因此可以嵌套调用对。

      【讨论】:

      • 但它仍在回收并为该项目调用 createViewholder...
      【解决方案4】:

      因为某些视图在不再可见时被销毁,然后 在 onBindViewHolder() 方法中重新创建。

      这不是真的,它们不会再次创建,它们只是重新绑定。如果您有位置 X 的视图(在废料或回收器中)RecyclerView 将使用它并重新绑定它。

      我想保留这些视图,因为它们每次都需要重新膨胀。

      主要的RecyclerView 为您保留这些。您只需要更改您的第二个RecyclerView 的适配器数据并调用notifyDataSetChanged。还将您的第二个RecyclerView 适配器存储在主RecyclerViewviewHolder 中。

      【讨论】:

      • 拯救我的一天 +1。
      【解决方案5】:

      在您的活动中设置以下行

      recyclerView.getRecycledViewPool().setMaxRecycledViews(1,0);

      在 RecyclerViewAdapter 类中设置下面的代码

      @Override
          public int getItemViewType(int position) {
              return 1;
          }
      

      【讨论】:

        【解决方案6】:

        我的代码在 recycleview 中用于重置 UI。

        public class BooleanViewHolder extends BaseViewHolder<ConfigItemBoolean> {
            private SwitchCompat configBoolean;
        
            BooleanViewHolder(View view) {
                super(view);
                configBoolean = view.findViewById(R.id.enable_config_boolean);
                configBoolean.setOnCheckedChangeListener((buttonView, isChecked) -> {
                    ((ConfigItemBoolean) getItem(getAdapterPosition())).setValue(isChecked);
                    DataSet.mConfigDataSet.getConfigItemBooleanMap().put(configPairList.get(getAdapterPosition()).first, ((ConfigItemBoolean) getItem(getAdapterPosition())));
                });
            }
        
            @Override
            void bind(ConfigItemBoolean item, String key) {
                configBoolean.setText(item.getDisplayName());
                configBoolean.setChecked(item.isValue());
            }
        
        }
        

        【讨论】:

          【解决方案7】:

          试试这个

          recyclerView.getRecycledViewPool().setMaxRecycledViews(youViewHolder type,0);
          

          如果你使用 viewHolder.setIsRecyclable(false);将在recyclerview中出现多个相同的viewholder

          【讨论】:

            猜你喜欢
            • 2022-11-19
            • 2013-10-19
            • 1970-01-01
            • 1970-01-01
            • 2021-05-22
            • 2023-04-07
            • 2021-04-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多