RecyclerView滚动到顶部,而AsyncListDiffer不起作用

时间:2019-03-20 13:53:21

标签: android android-recyclerview android-asynclistdiffer android-diffutils

我将RecyclerViewAsyncListDiffer一起使用(计算和动画化旧项目和新项目之间的差异,所有这些都在后台线程上。)

我有一个按钮可以对列表进行排序。在对它进行排序并使用RecyclerView将其重新设置为mDiffer.submitList(items);之后,我也调用了recyclerView.scrollToPosition(0)或(smoothScrollToPosition(0)),但是它没有任何作用。

我认为这种行为是可以预期的,因为AsyncListDiffer可能在调用scrollToPosition(0)时仍在计算差异,因此它没有任何作用。此外,默认情况下,AsyncListDiffer不会回滚到顶部,而是使RecyclerView保持相同的状态。

但是如何RecyclerView完成并更新后告诉AsyncListDiffer滚动到顶部?

3 个答案:

答案 0 :(得分:1)

在这里得到了答案:

https://stackoverflow.com/a/55264063/1181261

基本上,如果您以不同的顺序提交相同的列表,它将被忽略。因此,您首先需要submit(null),然后提交重新排序的列表。

答案 1 :(得分:1)

我担心,尽管.submitList(null)为您服务,但它只会刷新整个RecyclerView,而不会呈现所需的动画列表更新。

解决方案是在ListAdapter内部实现.submitList( List<T> list)方法,如下所示:

public void submitList(@Nullable List<T> list) {
    mDiffer.submitList(list != null ? new ArrayList<>(list) : null);
}

通过这种方式,您可以允许ListAdapter保留其currentList,并使其与newList“差异”,从而进行动画更新,而不是与null“差异”。

答案 2 :(得分:1)

如果查看AsyncListDiffer的{​​{1}}的javadocs,您会注意到第二个参数是submitList,它是在将项目提交到适配器之后执行的: / p>

Runnable

所以你想要的是这个(这是Kotlin顺便说一句):

/**
 * Pass a new List to the AdapterHelper. Adapter updates will be computed on a background
 * thread.
 * <p>
 * If a List is already present, a diff will be computed asynchronously on a background thread.
 * When the diff is computed, it will be applied (dispatched to the {@link ListUpdateCallback}),
 * and the new List will be swapped in.
 * <p>
 * The commit callback can be used to know when the List is committed, but note that it
 * may not be executed. If List B is submitted immediately after List A, and is
 * committed directly, the callback associated with List A will not be run.
 *
 * @param newList The new List.
 * @param commitCallback Optional runnable that is executed when the List is committed, if
 *                       it is committed.
 */

或使用Java

adapter.submitList(items) {
   // This will run after items have been set in the adapter
   recyclerView.scrollToPosition(0)
}