使用diff utils更新回收者视图适配器,添加项时无法正常工作

时间:2019-05-22 16:59:32

标签: android android-recyclerview item-decoration android-diffutils

我正在使用diff utils更新我的回收站视图(视图模型中的实时数据返回一个列表),我进行了项修饰,在列表中的最后一个元素上添加了大量填充,但是随着diff utils更新了通过调用notifyItemInserted而不是notifyDataSetChanged正确地访问回收者视图,该修饰仅应用于最后添加的元素,因此,如果我将一个项目添加到回收者视图中并调用通知数据集已更改,则我的所有项目最终都将以大量填充结尾适配器重建所有项目,并且填充仅在最后一个元素(这就是我想要的)上,如果我两次添加相同的项目,则它会在最后一次添加之前添加它,例如,如果我有1,2,3的列表我再添加3个,然后在现有的3个1,2,3b,3a之前添加它,有什么办法可以对此进行更多控制吗?

物品装饰

public class PredictionsHorizontalSpaceCardDecoration extends RecyclerView.ItemDecoration {

private final int horizontalSpace;
private final int endSpace;

public PredictionsHorizontalSpaceCardDecoration(int horizontalSpace, int endSpace) {
    this.horizontalSpace = horizontalSpace;
    this.endSpace = endSpace;
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    Log.d("Deco", "parent child count " + (parent.getChildCount() - 1) + " position " + parent.getChildAdapterPosition(view));
    outRect.right = horizontalSpace;
    outRect.top = horizontalSpace;
    outRect.bottom = horizontalSpace;
    outRect.left = horizontalSpace;

    if (parent.getChildAdapterPosition(view) == parent.getChildCount() - 1){
        outRect.right = endSpace;
    }
}

@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull State state) {
    super.onDraw(c, parent, state);
 }
}

差异工具

    public class MyDiffCallback extends DiffUtil.Callback{

      List<Card> oldCards;
      List<Card> newCards;
      String TAG = "diffUtils";

      public MyDiffCallback(List<Card> newCards, List<Card> oldCards) {
        this.newCards = newCards;
        this.oldCards = oldCards;
      }

      @Override
      public int getOldListSize() {
        return oldCards.size();
      }

      @Override
      public int getNewListSize() {
        return newCards.size();
      }

      @Override
      public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        boolean areItemsTheSame = oldCards.get(oldItemPosition).getCardId() == newCards.get(newItemPosition).getCardId();
        Log.d(TAG,"areItemsTheSame " + areItemsTheSame);
        return oldCards.get(oldItemPosition).getCardId() == newCards.get(newItemPosition).getCardId();
      }

      @Override
      public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        boolean areItemsTheSame = oldCards.get(oldItemPosition).equals(newCards.get(newItemPosition));
        Log.d(TAG,"areContentsTheSame " + areItemsTheSame);
        return oldCards.get(oldItemPosition).equals(newCards.get(newItemPosition));
      }

      @Nullable
      @Override
      public Object getChangePayload(int oldItemPosition, int newItemPosition) {
        //you can return particular field for changed item.
        Log.d(TAG,"getChangePayload ");
        return super.getChangePayload(oldItemPosition, newItemPosition);
    //    return newCards.get(newItemPosition).getCardId();
      }
    }

从回收者视图适配器更新

public class CalculateDiffUtils extends AsyncTask<Void, Void, DiffUtil.DiffResult> {

    private List<Card> oldCardList;
    private List<Card> newCardList;

    CalculateDiffUtils(List<Card> oldCardList, List<Card> newCardList) {
        this.oldCardList = oldCardList;
        this.newCardList = newCardList;
    }

    @Override
    protected DiffUtil.DiffResult doInBackground(Void... params) {
        return DiffUtil.calculateDiff(new MyDiffCallback(newCardList, oldCardList));
    }

    @Override
    protected void onPostExecute(DiffUtil.DiffResult diffResult) {
        super.onPostExecute(diffResult);
        dispatchUpdates(diffResult, newCardList);

    }
}




public void dispatchUpdates(DiffUtil.DiffResult diffResult, List<Card> newCardList){
    this.cardList.clear();
    this.cardList.addAll(newCardList);
    diffResult.dispatchUpdatesTo(this);
}

1 个答案:

答案 0 :(得分:0)

我有一个与您所描述的问题类似的问题,我发现此问题正在寻找答案。

我不知道这个细节是否会影响您,但是您在最后一个项目的位置使用了parent.getChildCount() - 1。我最初使用的是state.getItemCount()(减号1),但是事实证明这是一个问题,因为我的列表更改了大小。我最终使用了parent.getLayoutManager().getItemCount()方法(必需的null检查和偏移量)。

不过,我注意到,在玩添加和删除项目以及更改列表大小时,DiffUtil不会更新不需要重绘的项目,因此我实际上进行了检查以查看该项目是否被更改的是我列表中的最后一个,然后在相邻项目上调用了notifyItemChanged()。这样可以确保正确应用项目装饰。我在致电diffResult.dispatchUpdatesTo(this)notifyItemChanged(positionOfNewOrOldLastElement)之后添加了此权限。