Android SQLite新表无法存储数据,书签增删功能异常求助
解决你的Android SQLite书签存储/删除问题
先从你的崩溃日志入手,核心问题是NullPointerException——在DetailActivity.onCreate第54行调用mDBHelper.getBookmarkWord("")时,mDBHelper根本没完成初始化!这是最紧急的问题,我们一步步来解决:
第一步:修复DetailActivity的空指针崩溃
在DetailActivity的onCreate方法里,你只声明了DatabaseHelper mDBHelper;但没有实例化它,加上初始化和数据库准备代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_detail); getSupportActionBar().setDisplayHomeAsUpEnabled(true); // 新增:初始化数据库助手并确保数据库可用 mDBHelper = new DatabaseHelper(this); try { mDBHelper.createDataBase(); mDBHelper.openDatabase(); } catch (IOException e) { e.printStackTrace(); } // 原有业务代码... }
第二步:统一数据库表名,修复书签方法的表名混乱
你的代码里表名完全不一致:
- 定义了常量
TABLE_BOOKMARK= "bookmark",但onCreate创建的是favourites表 removeBookmark和getBookmarkWord里又硬编码用favourites,和常量脱节
1. 修正表创建逻辑
用常量创建表,同时明确字段类型(避免隐含错误):
@Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_BOOKMARK + " (" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COL_WORD + " TEXT NOT NULL," + COL_DEFINITION + " TEXT NOT NULL)"); }
2. 修正删除书签方法
用常量表名,并且用精准匹配替代模糊查询(避免误删),同时绑定参数防止SQL注入:
public void removeBookmark(String title, String subtitle) { SQLiteDatabase db = this.getWritableDatabase(); db.delete(TABLE_BOOKMARK, COL_WORD + " = ? AND " + COL_DEFINITION + " = ?", new String[]{title, subtitle}); db.close(); }
3. 修正获取书签方法
替换硬编码表名为常量:
public Cursor getBookmarkWord(String wordSearch) { String query = "SELECT * FROM " + TABLE_BOOKMARK + " Where word Like ? "; Cursor cursor = null; try { openDatabase(); String[] args = {"%"+wordSearch+"%"}; cursor = mDatabase.rawQuery(query , args); }catch (Exception e){ e.printStackTrace(); } return cursor; }
第三步:修复数据库初始化的逻辑漏洞
你的createDataBase方法会删除刚创建的书签表:当数据库不存在时,你先调用getReadableDatabase()触发onCreate创建bookmark表,然后立刻删除数据库再copy资产里的文件,导致刚创建的书签表丢失。修改逻辑:
public void createDataBase() throws IOException { boolean dbExist = checkDataBase(); if (!dbExist) { // 先触发onCreate创建书签表,再关闭临时数据库 SQLiteDatabase tempDb = this.getReadableDatabase(); tempDb.close(); // 再复制资产里的字典数据库 try { copyDataBase(); } catch (IOException e) { throw new Error("Error copying database"); } } else { // 数据库已存在时,检查书签表是否存在,不存在则创建 openDatabase(); Cursor cursor = mDatabase.rawQuery("SELECT name FROM sqlite_master WHERE type='table' AND name=?", new String[]{TABLE_BOOKMARK}); if (cursor.getCount() == 0) { onCreate(mDatabase); } cursor.close(); close(); } }
第四步:优化书签状态判断逻辑
原来的bookmarkWord == null判断错误——Cursor即使为空也不会是null,而是getCount() == 0,修正后还要记得关闭Cursor避免内存泄漏:
// 替换原有状态判断代码 Cursor bookmarkWord = mDBHelper.getBookmarkWord(word); int isMark = bookmarkWord.getCount() > 0 ? 1 : 0; btnBookmark.setTag(isMark); int icon = bookmarkWord.getCount() > 0 ? R.drawable.ic_bookmark_fill : R.drawable.ic_bookmark_border; btnBookmark.setImageResource(icon); bookmarkWord.close(); // 关闭Cursor
第五步:完善添加书签方法的返回逻辑
添加插入结果判断,确保操作成功:
public boolean addBookmark(String title, String subtitle) { SQLiteDatabase db = getWritableDatabase(); ContentValues values = new ContentValues(); values.put(COL_WORD, title); values.put(COL_DEFINITION, subtitle); // 插入成功返回新行ID,失败返回-1 long result = db.insert(TABLE_BOOKMARK, null, values); db.close(); return result != -1; }
把这些修改逐一应用后,应该能解决书签存储/删除的问题,同时修复崩溃的空指针错误。
内容的提问来源于stack exchange,提问作者Faisal Khan
相关产品推荐
相关产品推荐

