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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:59:38