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

使用SimpleCursorAdapter从SQL数据库填充ListView时程序崩溃

解决SimpleCursorAdapter填充ListView崩溃的问题

嘿,我之前做类似大学作业的时候也踩过这个坑!你的崩溃问题大概率是因为SimpleCursorAdapter有个容易被忽略的硬性要求:绑定的Cursor必须包含名为_id的主键列,这是很多新手容易漏掉的关键点。

核心问题分析

SimpleCursorAdapter内部依赖_id列来唯一标识ListView的每一行数据,如果你的数据库表没有这个列,或者列名不是严格的_id(比如写成id、task_id都不行),就会在实例化Adapter的时候直接崩溃。

看你的getAllRows函数是用SELECT *查询,那只要表结构里有_id列就没问题,但如果你的表创建时没加这个字段,那肯定会出问题。

分步解决方案

1. 检查并修正数据库表结构

打开你的DBAdapter类,找到创建表的SQL语句,确保包含_id主键字段,示例如下:

// 替换成你实际的列定义,必须保留_id字段
private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" +
        "_id INTEGER PRIMARY KEY AUTOINCREMENT," + // 这一行是核心要求
        COLUMN_NAME + " TEXT NOT NULL," +
        COLUMN_DATE + " TEXT NOT NULL" +
        ");";

如果之前已经创建过表,需要卸载当前APP后重新运行(SQLite不会自动更新已存在的表结构)。

2. 修正getAllRows函数

不需要手动调用c.moveToFirst(),SimpleCursorAdapter会自行处理Cursor的遍历逻辑,提前移动指针可能导致数据显示异常或空指针:

public Cursor getAllRows() {
    String query = "SELECT * FROM " + TABLE_NAME;
    Cursor c = db.rawQuery(query, null);
    // 删掉c.moveToFirst();这一行
    return c;
}

3. 优化populate函数的细节

  • 用this代替getBaseContext(),Activity本身就是Context,更稳妥
  • 增加Cursor为空的判断,避免空指针
  • 去掉不必要的类型强转(Android API 26+支持自动转换)
private void populate(){
    Cursor cursor = myDb.getAllRows();
    
    // 空Cursor判断,避免后续崩溃
    if (cursor == null || cursor.getCount() == 0) {
        return;
    }

    String[] backDB = new String[] {DBAdapter.COLUMN_NAME, DBAdapter.COLUMN_DATE};
    int[] toView = new int[] {R.id.textViewName, R.id.textViewDate};
    
    SimpleCursorAdapter myCursor = new SimpleCursorAdapter(
            this,
            R.layout.row_layout, 
            cursor, 
            backDB,
            toView, 
            0);
            
    ListView myList = findViewById(R.id.listViewTasks);
    myList.setAdapter(myCursor);
}

4. 记得关闭Cursor避免内存泄漏

在Activity的onDestroy方法里关闭Cursor和数据库连接,防止内存泄漏:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (myDb != null) {
        myDb.close();
    }
    // 如果Cursor是全局变量,也要在这里关闭
    // if (cursor != null && !cursor.isClosed()) {
    //     cursor.close();
    // }
}

按照上面的步骤调整后,应该就能解决崩溃问题,正常显示任务列表了。

内容的提问来源于stack exchange,提问作者O'Kara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:55:48