我正在使用 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();
}
如前所述,如果我只是以一种悠闲的方式一次单击一个,那么这很好用,但是如果我向按钮发送垃圾邮件,我就会崩溃。