我有一个有趣的情况,我的适配器有两种视图类型 - HEADER
和ITEM
。标题视图始终位于位置0.当我更新数据时,我使用DiffUtil
来获取数据的差异。要调度更新并重新绑定,我使用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);
}
....
所以我可以将偏移量(即始终存在的标题的1个原因)添加到DiffUtil
计算的位置以更新正确的元素。这很好。
当我还需要更新标头时,会出现问题。我手动计算标头差异并通知适配器。与DiffUtil
一起,代码如下所示:
DiffUtil.DiffResult diffResult = DiffUtil
.calculateDiff(new ItemDiffUtil(getItems(), newData));
Bundle headerDiff = getDiffPayload(newData);
dispatchUpdates(this, diffResult);
if (!isNullOrEmpty(headerDiff.keySet())) {
notifyItemChanged(0, headerDiff);
}
这是拒绝玩得很好。将多个更新分派给适配器(例如,插入3个项目),它会变得混乱,我可以在网格中看到重复的项目(只是通过Picasso加载的缩略图)。如果我注释掉notifyItemChanged(0, headerDiff);
,标题显然没有更新,但其他一切正常。
我的问题是,是否可以以更有意义的方式排列这些更新,以便我仍然可以使用DiffUtil
,但我的标题也会更新?
编辑:有趣的是,如果我使用AirBnb的Epoxy
代替我自己的RecyclerView
适配器
答案 0 :(得分:1)
我仍然不确定为什么会这样,但我认为罪魁祸首是Picasso
。我在日志中注意到了一些事情:
问题出现后,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已经解决了这个问题。