如果您的适配器中有稳定的 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