Android读取SQLite数据存入List时RecyclerView不显示且Cursor报错
问题描述
尝试读取SQLite数据库中的全部数据并展示到RecyclerView时,列表无任何内容,同时应用抛出如下异常:
E/CursorWindow: Failed to read row 0, column 3 from a CursorWindow which has 4 rows, 3 columns. D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.uspherejda, PID: 7434 java.lang.IllegalStateException: Couldn't read row 0, col 3 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
问题原因
代码存在三处明显问题:
- Cursor列索引取值错误:SQL查询返回的游标列索引从0开始计数,你查询的三个字段
name、country、category对应的索引分别为0、1、2,但是代码中使用getString(1)、getString(2)、getString(3)取值,尝试读取不存在的第3列,直接触发越界崩溃。 - Cursor遍历逻辑错误:先调用
c.moveToFirst()将游标定位到第一条数据,循环条件又直接执行c.moveToNext(),会直接跳过第一条数据,如果库中只有1条数据,循环根本不会执行,返回的列表为空。 - 插入数据参数顺序错误:
SatelliteForm有参构造的参数顺序为(name, country, category),但插入数据时你传入的参数是(卫星名, 分类名, 国家名),导致国家和分类字段的存储值完全颠倒。
修复方案
1. 修复数据库查询逻辑
public ArrayList<SatelliteForm> getAllData(SQLiteDatabase sqLiteDatabase){ ArrayList<SatelliteForm> arraySatelite = new ArrayList<>(); sqLiteDatabase = this.getWritableDatabase(); String SELECT_QUERY = "select name, country, category from " + SatFormContracts.ContactsEntry.TABLE_NAME + ";"; Cursor c = sqLiteDatabase.rawQuery(SELECT_QUERY, null); // 移除多余的moveToFirst,直接用moveToNext遍历所有数据 while(c.moveToNext()){ SatelliteForm form = new SatelliteForm(); // 索引改为从0开始 form.setName(c.getString(0)); form.setCountry(c.getString(1)); form.setCategory(c.getString(2)); arraySatelite.add(form); Log.i("nameSQL", c.getString(0) + "" + c.getString(1) + "" + c.getString(2)); } c.close(); return arraySatelite; }
2. 修复插入数据参数顺序
public void onClick(View view) { if(!(satName.getText().toString().isEmpty() || countryName.getText().toString().isEmpty() || categoryName.getText().toString().isEmpty())){ // 调整参数顺序为(name, country, category) SatelliteForm addForm = new SatelliteForm(satName.getText().toString(), countryName.getText().toString(), categoryName.getText().toString()); dbHelper.insertContact(db, addForm); saveState.setText("保存成功!"); }else{ saveState.setText("存在未填写的字段"); Log.i("Campos", "Unos de los campos esta vacio"); } }
优化建议
为了避免手动写列索引出错,推荐通过字段名获取索引:
int nameIndex = c.getColumnIndexOrThrow("name"); int countryIndex = c.getColumnIndexOrThrow("country"); int categoryIndex = c.getColumnIndexOrThrow("category"); form.setName(c.getString(nameIndex)); form.setCountry(c.getString(countryIndex)); form.setCategory(c.getString(categoryIndex));
内容的提问来源于stack exchange,提问作者noobieCoder
相关产品推荐
相关产品推荐

