【问题标题】:How to completely resort RecyclerView's SortedList如何完全使用 RecyclerView 的 SortedList
【发布时间】:2015-04-22 12:48:36
【问题描述】:

RecyclerView 库最近添加了新的SortedList 类。假设我有一个回调,它实现了一个可以随时间改变的compare() 方法,即底层的 Comparator 可以被关闭。告诉SortedList 完全利用其数据的最佳方法是什么?

【问题讨论】:

  • 如果我必须猜测,beginBatchedUpdates()recalculatePositionOfItemAt()(每个项目)和endBatchedUpdates(),但这只是基于 API 的猜测。
  • 最坏的情况下,developer.android.com/reference/android/support/v7/widget/util/… 回调具有用于更改元素时的方法,但正确的答案可能是 @CommonsWare 的答案。
  • 这不是一个糟糕的开始。但是为每个索引调用 recalculatePositionOfItemAt() 不会完全使用它。索引会发生变化,这会导致某些项目被跳过。

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


【解决方案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()

【讨论】:

    【解决方案2】:

    不幸的是,没有用于此的 api。 只需复制源代码并自己添加该方法即可。支持数据只是一个数组,因此您可以在其上调用 Arrays.sort,然后调用通知数据集已更改。 当整个世界发生变化时,跟踪变化并非易事,因此不太适合排序列表。 请在 b.Android.com 上创建功能请求。

    【讨论】:

    • 是的,我意识到用超过 5 个项目制作完整的动画看起来真的很奇怪。
    • 顺便说一句,你不需要复制源代码。由于底层数组 mData 是包私有的,因此您可以通过同一包中的帮助程序访问它。
    【解决方案3】:

    以下方法对我有用,可以切换到新的比较器以重新排序列表。通过额外调用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();
    }
    

    【讨论】:

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