RecyclerView库最近添加了新的SortedList
类。假设我有一个回调实现了compare()
方法,该方法可以随时间变化,即可以切换基础比较器。告诉SortedList
完全使用其数据的最佳方法是什么?
答案 0 :(得分:1)
这是我自己的看法(用Kotlin写的):
list.beginBatchedUpdates()
val indices = (0..list.size() - 1).toArrayList()
while (!indices.isEmpty()) {
val i = indices.first()
val item = list.get(i)
list.recalculatePositionOfItemAt(i)
[suppress("USELESS_CAST_STATIC_ASSERT_IS_FINE")]
indices.remove(list.indexOf(item) as Any) //cast to disambiguate remove()
}
list.endBatchedUpdates()
正如您所看到的,我在每次调用recalculatePositionOfItemAt()
后跟踪新索引,因此每个项目只使用一次,并且不会跳过任何项目。
这可行,但看起来真的很浪费,因为recalculatePositionOfItemAt()
将调整基础数组的大小两次以删除然后读取该项目。然后indexOf
将执行新的二进制搜索,即使索引已知。
编辑:如果项目比较相等,这似乎会导致无限循环。
替代方法(全部删除,然后全部添加):
list.beginBatchedUpdates()
val copy = (list.size() - 1 downTo 0).map { list.removeItemAt(it) }
copy.forEach { list.add(it) }
list.endBatchedUpdates()
答案 1 :(得分:0)
不幸的是,这没有api。 只需复制源并自己添加该方法。支持数据只是一个数组,因此您可以在其上调用Arrays.sort,然后调用通知数据集更改。 当整个世界发生变化时跟踪变化并不是微不足道的,因此不适合排序列表。 请在b.Android.com上创建功能请求。
答案 2 :(得分:0)
以下方法对我有用,可以切换到新的比较器以重新排序列表。我发现动画更加流畅了,另外调用了notifyDataSetChanged()
private final List<MyObject> mTmp = new ArrayList<>();
private Comparator<MyObject> mComparator = DEFAULT_COMPARATOR;
private final SortedList<MyObject> mSortedList = new SortedList<>(MyObject.class, new SortedList.Callback<MyObject>() {
@Override
public int compare(MyObject a, MyObject b) {
return mComparator.compare(a, b);
}
// and other methods...
});
public void changeComparator(@NonNull Comparator<MyObject> comp) {
mComparator = comp;
mSortedList.beginBatchedUpdates();
for(int i = 0; i < mSortedList.size(); ++i) {
mTmp.add(mSortedList.get(i));
}
mSortedList.clear();
mSortedList.addAll(mTmp);
mTmp.clear();
mSortedList.endBatchedUpdates();
notifyDataSetChanged();
}