Android ListView点击项查询SQLite单条数据时应用崩溃问题
解决ListView点击查询数据库崩溃的问题
从你的LogCat信息里一眼就能定位到核心问题:NullPointerException,原因是UserDbHelper的getRow方法里的SQLiteDatabase对象db根本没初始化,就直接调用execSQL了。而且还有个用法错误:execSQL是用来执行无返回结果的SQL语句(比如建表、插入数据),查询数据得用能返回Cursor的方法。下面一步步帮你修复:
1. 修复UserDbHelper的getRow方法
原来的方法里db变量是空的,还误用了查询方法,改成下面这样:
// Get a specific row (by rowId) public Cursor getRow(long rowId) { // 直接获取可读数据库实例,不用依赖未初始化的成员变量 SQLiteDatabase db = getReadableDatabase(); // 用参数化查询,避免SQL注入风险,更规范 String selection = UserContract.NewUserInfo.USER_ROWID + " = ?"; String[] selectionArgs = {String.valueOf(rowId)}; // 指定要查询的列,只查需要的user_name String[] projection = {UserContract.NewUserInfo.USER_NAME}; // 使用Android推荐的query方法执行查询 Cursor cursor = db.query( UserContract.NewUserInfo.TABLE_NAME, projection, selection, selectionArgs, null, null, null ); return cursor; }
关键改动说明:
- 用
getReadableDatabase()直接获取数据库实例,彻底解决成员变量db未初始化的空指针问题。 - 替换字符串拼接为参数化查询(
?占位符),既避免SQL注入风险,也让代码更健壮。 - 用
query方法替代execSQL,因为execSQL不会返回查询结果,我们需要Cursor来获取目标用户名。
2. 修复ListView点击事件的参数错误
你在onItemClick里把i(列表项的position)传给了getRow,但实际上onItemClick的第四个参数rowId才是对应数据库里的行ID(从你的Log看之前ID刚好匹配,但必须用正确参数保证兼容性)。另外,用完Cursor要记得关闭,避免内存泄漏:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) { Cursor cursor = user.getRow(rowId); // 先判断cursor不为空,再执行后续操作 if(cursor != null && cursor.moveToFirst()){ String userName = cursor.getString(0); String message = "用户名: " + userName; Toast.makeText(ListActivity.this, message, Toast.LENGTH_SHORT).show(); cursor.close(); // 用完Cursor一定要关闭! } } });
额外建议
- 数据库操作最好放在子线程中执行,避免阻塞主线程导致ANR(应用无响应),简单查询当前场景没问题,但复杂操作一定要异步处理。
- 确保
UserContract里的常量(比如USER_ROWID、USER_NAME)和数据库表的字段名完全一致,否则会出现查询不到数据的情况。
内容的提问来源于stack exchange,提问作者user9154383
相关产品推荐
相关产品推荐

