Android集成WordPress API排序时ArrayIndexOutOfBoundsException求助
问题:RecyclerView切换排序时出现ArrayIndexOutOfBoundsException异常
加载完12篇文章滚动到底部后,点击「最多浏览」「最多评论」等排序按钮,出现如下异常:
java.lang.ArrayIndexOutOfBoundsException: length=22; index=-1 at java.util.ArrayList.remove(ArrayList.java:506) at com.testtest.test.PostAdapter.showHideProgress(PostAdapter.java:158) at com.testtest.test.MainActivity$7.onResponse(MainActivity.java:293)
相关代码
PostAdapter核心代码
private List<Model> dataset; // ... 其他成员变量 public void clearApplications() { int size = this.dataset.size(); if (size > 0) { for (int i = 0; i < size; i++) { dataset.remove(0); } this.notifyItemRangeRemoved(0, size); } } void showHideProgress(boolean shouldShowProgress){ if (shouldShowProgress){ dataset.add(new Model("progress","","","","","","","","","","")); Handler handler = new Handler(); final Runnable r = new Runnable() { public void run() { notifyItemInserted(dataset.size()-1); } }; handler.post(r); }else { dataset.remove(dataset.size()-1); notifyItemRemoved(dataset.size()-1); } } // ... 其他方法
排序按钮触发代码
if (id == R.id.action_view) { adapter.clearApplications(); yourURL = baseURL + mostView; getRetrofit(); tv.setVisibility(View.VISIBLE); return true; }
尝试过的修改
修改了clearApplications方法,但问题未解决:
public void clearApplications() { int size = this.dataset.size() -1; if (size > 0) { for (int i = 0; i < size; i++) { dataset.remove(0); } this.notifyItemRangeRemoved(0, size); } }
解决方案
1. 修复showHideProgress数组越界问题
异常根源是切换排序后,旧的网络请求回调执行showHideProgress(false)时,列表已被清空,导致dataset.size()-1为-1。添加判断避免越界:
void showHideProgress(boolean shouldShowProgress){ if (shouldShowProgress){ // 避免重复添加progress item if(!dataset.isEmpty() && "progress".equals(dataset.get(dataset.size()-1).title)){ return; } dataset.add(new Model("progress","","","","","","","","","","")); notifyItemInserted(dataset.size()-1); }else { // 列表为空或最后一个不是progress时直接返回 if(dataset.isEmpty() || !"progress".equals(dataset.get(dataset.size()-1).title)){ return; } dataset.remove(dataset.size()-1); notifyItemRemoved(dataset.size()); // remove后size已减1,用当前size作为移除位置 } }
2. 优化clearApplications方法
循环移除第一个元素效率极低,直接清空列表并通知更新:
public void clearApplications() { int size = dataset.size(); if (size > 0) { dataset.clear(); notifyItemRangeRemoved(0, size); } }
3. 切换排序时取消未完成的网络请求
避免旧请求回调触发无效操作,用Retrofit的话保存当前请求并取消:
// 全局保存当前请求 private Call<List<Model>> currentRequest; // 触发排序的方法中 if(currentRequest != null && !currentRequest.isCanceled()){ currentRequest.cancel(); } currentRequest = apiService.getPosts(yourURL); currentRequest.enqueue(new Callback<List<Model>>() { // ... 回调逻辑 });
4. 修正ViewType识别逻辑
当前代码未处理progress类型的item,导致RecyclerView无法正确加载布局,补充逻辑:
@Override public int getItemViewType(int position){ // 计算真实数据位置,排除广告项 int realPos = position - (position / LIST_AD_DELTA); if(realPos >= dataset.size()){ return viewTypeData; } Model model = dataset.get(realPos); if("progress".equals(model.title)){ return viewTypeProgress; } if (position > 0 && position % LIST_AD_DELTA == 0) { return AD; } return viewTypeData; }
内容的提问来源于stack exchange,提问作者noorapps
相关产品推荐
相关产品推荐

