2

我正在使用 diff utils 回调更新 RecyclerView 它似乎工作正常,除非我单击适配器中的视图(这会强制视图基本上随机播放)超快我的应用程序将因 IndexOutOfBoundsException 崩溃:索引:25,大小:30 ,除了根据日志它没有超出范围,我认为这是因为我在异步任务中使用 diff utils,但我认为这是如何做到的,在后台处理(好像列表很大diff utils 计算量很大)并发布到适配器?任何帮助将不胜感激,这是我的

可访问的差异工具

  public class VisitableDiffUtils extends DiffUtil.Callback {

    private final List<Visitable> oldVisitable;
    private final List<Visitable> newVisitable;
    private final String TAG = "DIFFUTIL";
    private final TypeFactory typeFactory;

    public VisitableDiffUtils(List<Visitable> oldVisitable,
                              List<Visitable> newVisitable) {
      this.typeFactory = new TypeFactoryForList();
      this.oldVisitable = oldVisitable;
      this.newVisitable = newVisitable;
    }


    @Override
    public int getOldListSize() {
      return oldVisitable != null ? oldVisitable.size() : 0;
    }

    @Override
    public int getNewListSize() {
      return newVisitable != null ? newVisitable.size() : 0;
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {

      return Objects.equals(oldVisitable.get(oldItemPosition).id(),
              newVisitable.get(newItemPosition).id());

    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
      return oldVisitable
          .get(oldItemPosition).toString().equals(newVisitable.get(newItemPosition).toString());
    }

    @Nullable
    @Override
    public Object getChangePayload(int oldItemPosition, int newItemPosition) {
      Log.d(TAG,"getChangePayload");
      if (newVisitable.get(newItemPosition).type(typeFactory) == CardViewHolder.LAYOUT){
        Sentence newSentence = (Sentence) newVisitable.get(newItemPosition);
        Sentence oldSentence = (Sentence) oldVisitable.get(oldItemPosition);
        Bundle diffBundle = new Bundle();
        if (newSentence.getClicks() != oldSentence.getClicks()) {
          Log.d(TAG,"putInt(Constants.CARD_CLICKED");
          diffBundle.putInt(Constants.CARD_CLICKED, newSentence.getClicks());
        }
        if (diffBundle.size() == 0) return null;
        return diffBundle;
      } else {
        GroupsWithSentences newSentence = (GroupsWithSentences) newVisitable.get(newItemPosition);
        GroupsWithSentences oldSentence = (GroupsWithSentences) oldVisitable.get(oldItemPosition);
        Bundle diffBundle = new Bundle();
        if (newSentence.getGroupItems().size() != oldSentence.getGroupItems().size()) {
          diffBundle.putInt(Constants.CARD_CLICKED, newSentence.getGroupItems().size());
        }
        if (diffBundle.size() == 0) return null;
        return diffBundle;
      }
    }
  }

崩溃记录

Caused by: java.lang.IndexOutOfBoundsException: Index: 25, Size: 30
    at java.util.ArrayList.get(ArrayList.java:437)
    at VisitableDiffUtils.areItemsTheSame(VisitableDiffUtils.java:47)

和我的适配器中的代码

当我想更新它时,我调用 refreshDiffUtilsList

class CalculateDiffUtils extends AsyncTask<Void, Void, DiffResult> {

    private final List<Visitable> oldCardList;
    private final List<Visitable> newCardList;

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

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

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

private void dispatchUpdates(DiffUtil.DiffResult diffResult, List<Visitable> newCardList) {
    this.elements.clear();
    this.elements.addAll(newCardList);
    diffResult.dispatchUpdatesTo(this);
}

public void refreshDiffUtilsList(List<Visitable> sentences) {
    new CalculateDiffUtils(elements, sentences).execute();
}

如前所述,如果我只是以一种悠闲的方式一次单击一个,那么这很好用,但是如果我向按钮发送垃圾邮件,我就会崩溃。

4

0 回答 0