如果您的适配器中有稳定的ID,那么如果创建一个包含过滤后的项目的新数组并调用,则可以获得很好的效果(动画)
recyclerView.swapAdapter(newAdapter, false);
使用swapAdapter提示RecyclerView它可以重新使用视图持有者。 (与setAdapter相比,它必须回收所有视图并重新创建,因为它不知道新适配器具有与旧适配器相同的ViewHolder集)。
更好的方法是找到要删除的项目并致电notifyItemRemoved。不要忘记实际删除项目。 这将使RecyclerView运行预测性动画。 假设您有一个内部使用ArrayList的适配器,则实现如下所示:
// adapter code
final List 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消除方法性能(要转移的项目较少)。
例如,如果您从头开始遍历列表,则删除前两个项目。你应该打电话
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