Обновление адаптера представления переработчика с помощью утилит diff, работает неправильно при добавлении элемента

Я использую утилиты diff для обновления моего представления рециркулятора (текущие данные из модели представления возвращают список), у меня есть оформление элемента, которое добавляет большое количество отступов к последнему элементу в списке, но поскольку утилиты diff правильно обновляют представление рециркулятора вызывая notifyItemInserted, а не notifyDataSetChanged, оформление применяется только к последнему элементу ADDED, поэтому все мои элементы заканчиваются большим количеством отступов в конце, если я добавляю элемент в представление своего рециркулятора и вызываю набор данных notify, изменяющий адаптер, перестраивает все элементы и отступы находятся только на последнем элементе (что я и хочу), также, если я добавляю один и тот же элемент дважды, он добавляет его перед последним добавленным, например, если у меня есть список 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);
 }
}

Diff утилит

    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);
}

0 ответов

У меня была проблема, похожая на то, что вы описываете, и я нашел это в поисках ответа.

Не знаю, влияет ли на вас эта деталь, но вы используете parent.getChildCount() - 1для последней позиции элемента. Изначально я использовалstate.getItemCount()(минус один), но это оказалось проблемой, поскольку мой список меняет размер. В итоге я использовалparent.getLayoutManager().getItemCount() метод (с необходимой нулевой проверкой и смещением).

Однако я заметил, что, играя с добавлением и удалением элементов и изменяя размер списка, DiffUtil не обновлял элементы, которые не нужно было перерисовывать, поэтому я действительно проверил, был ли изменен элемент был последним в моем списке, а затем позвонил notifyItemChanged()на соседнем элементе. Это обеспечит правильное нанесение украшения на предмет. Я добавил это сразу после того, как позвонилdiffResult.dispatchUpdatesTo(this) т.е. notifyItemChanged(positionOfNewOrOldLastElement).

Другие вопросы по тегам