android - RecyclerView 在手动和通过 DiffUtil 通知更改时会感到困惑

标签 android android-recyclerview

我遇到了一个有趣的情况,我的适配器有 2 种 View 类型 - HEADERITEM。标题 View 始终位于位置 0。当我更新数据时,我使用 DiffUtil 来获取数据的差异。为了分派(dispatch)更新并重新绑定(bind),我使用 ListUpdateCallback:

private void dispatchUpdates(
        @NonNull final RecyclerView.Adapter adapter,
        @NonNull DiffUtil.DiffResult result) {
    result.dispatchUpdatesTo(new ListUpdateCallback() {
        @Override
        public void onInserted(int position, int count) {
            adapter.notifyItemRangeInserted(position + getItemOffset(), count);
        }
    ....

因此我可以将偏移量(即始终存在的 header 的 1 个原因)添加到由 DiffUtil 计算的位置,以更新正确的元素。这工作得很好。

当我还需要更新 header 时,就会出现问题。我手动计算 header 差异并通知适配器。与 DiffUtil 一起使用,代码如下所示:

        DiffUtil.DiffResult diffResult = DiffUtil
                .calculateDiff(new ItemDiffUtil(getItems(), newData));
        Bundle headerDiff = getDiffPayload(newData);
        dispatchUpdates(this, diffResult);
        if (!isNullOrEmpty(headerDiff.keySet())) {
            notifyItemChanged(0, headerDiff);
        }

这就是拒绝好好发挥。由于将多个更新分派(dispatch)到适配器(例如,插入 3 个项目),它会变得困惑,我可以在网格中看到重复的项目(只是通过 Picasso 加载的缩略图)。如果我注释掉 notifyItemChanged(0, headerDiff); header 显然没有更新,但其他一切都正常。

我的问题是是否可以以更有意义的方式对这些更新进行排队,以便我仍然可以使用 DiffUtil 但我的 header 也会更新?

编辑:有趣的是,如果我使用 AirBnb 的 Epoxy 而不是我自己的 RecyclerView 适配器,同样的问题仍然存在

最佳答案

我仍然不确定为什么会发生这种情况,但我认为罪魁祸首是毕加索。我注意到日志中的一些内容:

当问题出现时,Picasso 永远不会完成请求:

D/Picasso: Main        created      [R14655] Request{content://com.app.myapp.contentprovider/thumb/20170705173259427 resize(534,534) centerCrop}
D/Picasso: Dispatcher  enqueued     [R14655]+0ms 
D/Picasso: Hunter      executing    [R14655]+0ms 
D/Picasso: Hunter      removed      [R14655]+4ms from 
D/Picasso: Dispatcher  canceled     [R14655]+4ms 

此外,Picasso 还发生了一些奇怪的事情,因为它进入无限循环,为网格中的每个元素创建请求:

D/Picasso: Main        created      [R14424] Request{content://com.app.myapp.contentprovider/thumb/20170705173054794 resize(534,534) centerCrop}
D/Picasso: Main        completed    [R14424] from MEMORY
<...> // repeated for each ViewHolder forever in an endless loop

无论如何,请转到 Glide据我所知已经解决了这个问题。

关于android - RecyclerView 在手动和通过 DiffUtil 通知更改时会感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44905859/

相关文章:

android - 嵌套的 recyclerview 在前几次滚动然后平滑滚动时滞后?

android - TextViews不在约束布局中移至“开始”位置

使用recyclerview时Android fragment 滚动所有元素

java - 如何将 onSaveInstance 方法与 Recyclerview 一起使用

Android Studio - ScrollView 在键盘打开时移出屏幕

不支持 Android 应用程序、设备 (Galaxy Mini)

java - Android Java - 防止使用大量位图的 GC_FOR_ALLOC

android - 如何使用 JSOUP 解析 Android 中的嵌套 div?

android - 快速滚动 recyclerView 列表时,RecyclerView 内的 NetworkImageView 有时不会加载图像。 Volley 网络响应缓慢

android - 更新 HAXM 后,Android API 28 的模拟器无法启动