如何完全采用RecyclerView的SortedList

时间:2015-04-22 12:48:36

标签: java android android-support-library android-recyclerview kotlin

RecyclerView库最近添加了新的SortedList类。假设我有一个回调实现了compare()方法,该方法可以随时间变化,即可以切换基础比较器。告诉SortedList完全使用其数据的最佳方法是什么?

3 个答案:

答案 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();
}