SQLite数据已写入但RecyclerView填充时触发IndexOutOfBoundException求助
首先咱们得先抓准这个异常的核心:RecyclerView的Adapter拿到的数据集大小,和实际绑定视图时用的位置不匹配——要么是getItemCount()返回的数量不对,要么是数据集更新时没通知Adapter,再或者是绑定逻辑里误用了索引。结合你描述的情况,咱们一步步来排查:
1. 先检查Adapter的getItemCount()方法
这是最容易踩坑的地方,你得确保这个方法返回的是从SQLite查出来的数据集的真实大小。比如你的数据集是List<MyModel> dataList,那getItemCount()得写成这样:
@Override public int getItemCount() { // 避免空指针,同时返回真实的列表长度 return dataList != null ? dataList.size() : 0; }
要是这里返回了固定值(比如写死10),或者计算错了长度,肯定会触发越界异常。
2. 验证SQLite查询的数据集是否正确
你说插入数据时日志能看到,但得确认查询出来的数据集真的加载到Adapter里了。可以在查询完数据后打印下列表大小,比如:
// 从SQLite查询数据 List<MyModel> newData = dbHelper.fetchAllData(); Log.d("DB_CHECK", "查询到的数据条数:" + newData.size()); // 更新Adapter的数据集并通知更新 adapter.updateData(newData); adapter.notifyDataSetChanged();
要是日志里的条数和你预期的不一样,那得先排查SQLite的查询语句有没有问题,比如是不是漏了某些数据,或者字段映射错了。
3. 规范OnBindViewHolder的绑定逻辑
在绑定视图的时候,一定要先判断position是否在合法范围内,别直接拿position去取数据。比如:
@Override public void onBindViewHolder(MyViewHolder holder, int position) { // 先做合法性校验,避免越界 if (dataList == null || position >= dataList.size()) { return; } MyModel item = dataList.get(position); // 绑定数据到视图 holder.tvName.setText(item.getName()); holder.tvContent.setText(item.getContent()); }
别出现dataList.get(position + 1)这种错误写法,或者在分支逻辑里误用了其他索引值。
4. 数据集更新时必须通知Adapter
当你往SQLite插入新数据后,一定要重新查询数据,更新Adapter的数据集,然后调用notifyDataSetChanged()(或者更高效的notifyItemInserted())。要是没通知,Adapter还拿着旧的数据集大小,自然会出现越界。
比如插入数据后的正确流程:
// 插入数据到SQLite dbHelper.insertData(new MyModel("测试名称", "测试内容")); // 重新查询最新数据 List<MyModel> updatedData = dbHelper.fetchAllData(); // 更新Adapter的数据集 adapter.setData(updatedData); // 通知Adapter刷新视图 adapter.notifyDataSetChanged();
5. 排查SQLite表结构和查询语句
确保你的查询语句能正确取出所有数据,表结构和实体类的字段也对应上。比如查询时别漏了字段,或者getColumnIndex的时候写错了字段名:
public List<MyModel> fetchAllData() { List<MyModel> dataList = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT id, name, content FROM my_table", null); if (cursor.moveToFirst()) { do { MyModel model = new MyModel(); model.setId(cursor.getInt(cursor.getColumnIndex("id"))); model.setName(cursor.getString(cursor.getColumnIndex("name"))); model.setContent(cursor.getString(cursor.getColumnIndex("content"))); dataList.add(model); } while (cursor.moveToNext()); } cursor.close(); db.close(); return dataList; }
要是按上面的步骤排查后还是有问题,可以把完整的getItemCount()、OnBindViewHolder以及SQLite查询代码贴出来,咱们再细揪问题~
内容的提问来源于stack exchange,提问作者payal garg

