You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 15:24:01