【问题标题】:RecyclerView change data setRecyclerView 更改数据集
【发布时间】:2014-10-29 16:32:07
【问题描述】:

我想为我的 RecyclerView 实现搜索功能。在文本更改时,我想更改使用此小部件显示的数据。也许这个问题之前已经问过或者很简单,但是我不知道如何更改要显示的数据...

我的 RecyclerView 定义如下:

     // 1. get a reference to recyclerView
    mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView);

    // 2. set layoutManger
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    // 3. create an adapter
    mAdapter = new ItemsAdapter(itemsData);
    // 4. set adapter
    mRecyclerView.setAdapter(mAdapter);

我显示的数据类似于:

   ItemData itemsData[] = { new ItemData("Mary Richards"),
        new ItemData("Tom Brown"),
        new ItemData("Lucy London")          
};

那么当我想给适配器另一组数据,另一个数组(比如一个item)时,我应该怎么做呢?

【问题讨论】:

  • 如果你想提供另一个数组,你可以用它创建一个新的ItemsAdapter,然后再次调用setAdapter

标签: android android-recyclerview


【解决方案1】:

如果您的适配器中有稳定的 id,如果您创建一个包含过滤项的新数组并调用

,则可以获得非常好的结果(动画)
recyclerView.swapAdapter(newAdapter, false);

使用swapAdapter 暗示 RecyclerView 它可以重用视图持有者。 (与 setAdapter 相比,它必须回收所有视图并重新创建,因为它不知道新适配器与旧适配器具有相同的 ViewHolder 集)。

更好的方法是找出哪些项目被删除并调用notifyItemRemoved(index)。不要忘记实际删除该项目。这将使 RecyclerView 运行预测动画。假设您有一个内部使用 ArrayList 的适配器,实现将如下所示:

// adapter code
final List<ItemData> mItems = new ArrayList(); //contains your items
public void filterOut(String filter) {
   final int size = mItems.size();
   for(int i = size - 1; i>= 0; i--) {
       if (mItems.get(i).test(filter) == false) {
           mItems.remove(i);
           notifyItemRemoved(i);
       }
   }
}

如果您可以批处理notifyItemRemoved 调用并改用notifyItemRangeRemoved,它的性能会更好。它看起来像:(未测试)

public void filterOut(String filter) {
   final int size = mItems.size();
   int batchCount = 0; // continuous # of items that are being removed
   for(int i = size - 1; i>= 0; i--) {
       if (mItems.get(i).test(filter) == false) {
           mItems.remove(i);
           batchCount ++;
       } else if (batchCount != 0) { // dispatch batch
           notifyItemRangeRemoved(i + 1, batchCount);
           batchCount = 0;
       }
   }
   // notify for remaining
   if (batchCount != 0) { // dispatch remaining
       notifyItemRangeRemoved(0, batchCount);
   }
}

您需要扩展此代码以添加以前被过滤掉但现在应该可见的项目(例如用户删除过滤器查询),但我认为这个应该给出基本的想法。

请记住,每个通知项调用都会影响它之后的那些(这就是为什么我要从末尾遍历列表以避免它)。从末端遍历也有助于 ArrayList 的 remove 方法性能(需要移动的项目更少)。

例如,如果您从头开始遍历列表并删除前两项。 你应该打电话

notifyItemRangeRemoved(0, 2); // 2 items starting from index 0

或者如果你一个接一个地派他们

notifyItemRemoved(0);
notifyItemRemoved(0);//because after the previous one is removed, this item is at position 0

【讨论】:

  • 感谢您的回复,我会根据自己的需要进行调整,但这基本上是我需要的。你解释得很好。
  • “稳定ID”是什么意思?我的数据集发生了变化,但我不知道以什么方式(可能会添加一些新项目,可能会删除一些新项目)但视图保持不变,所以我应该将 true 还是 false 传递给 swapAdapter?
  • 关于“stable ids”解决方案的说明:您不需要隐式调用swapAdapter()。它工作正常,是的。但是任何其他解决方案,例如使用相同的适配器,并更改后备列表项都一样好,只要您调用notifyDataSetChanged()
  • swapAdapter 很棒!从来不知道这个方法。经过这么多年。谢谢!
  • sawpAdapter 现在已从库中删除。有没有办法切换到不同的适配器?
【解决方案2】:

这是我的答案 - 感谢他网站上的 Ivan Skoric:http://blog.lovelyhq.com/creating-lists-with-recyclerview-in-android/

我在适配器类中创建了一个额外的方法:

public void updateList(List<Data> data) {
    mData = data;
    notifyDataSetChanged();
}

然后每次你的数据发生变化时,你只需调用这个方法传入你的新数据,你的视图应该会改变以反映它。

【讨论】:

  • notifyDataSetChanged() 杀死所有动画,只对大列表有用。
  • @Davidea ...这是RecyclerView的典型用例
  • 回收视图仅将可见视图保留在内存中,并在您将它们从屏幕上滚动时释放它们。与列表视图相比,从内存的角度来看,它是高效的。它们的操作类似于列表视图。您可以在此处阅读 recyclerview 文档:developer.android.com/reference/android/support/v7/widget/…
  • 我使用处理程序从网络获取数据并使用它来更改数据,但有时即使数据没有更改,它也会将数据添加到以前的项目
【解决方案3】:

只需重新初始化您的适配器:

mAdapter = new ItemsAdapter(newItemsData);

或者如果您只需要删除一些特定项目而不是整个列表:

mAdapter.notifyItemInserted(position);

mAdapter.notifyItemRemoved(position);

【讨论】:

    【解决方案4】:

    如果您想在回收站视图中更改完整的适配器。你可以简单地通过recycler.setAdapter(myAdapter);设置 它会自动从回收站视图中删除旧适配器并用新适配器替换它。

    【讨论】:

      【解决方案5】:

      正如 ygit 回答的那样,swapAdapter 在您必须更改整个内容时很有趣。

      但是,在我的 FlexibleAdapter 中,您可以使用 updateDataSet 更新项目。您甚至可以将适配器配置为调用notifyDataSetChanged 或具有同步动画(默认启用)。那是因为 notifyDataSetChanged 会杀死所有的动画,但是对于大列表来说还是不错的。

      请查看描述、demoApp 和 Wiki 页面:https://github.com/davideas/FlexibleAdapter

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多