Android singleton SQLite,IllegalStateException:尝试重新打开已经关闭的对象:SQLiteDatabase

时间:2014-09-10 10:19:17

标签: android sqlite

我正在使用SQLite SQLiteAssetHelper 2.0.1。我实现了一个单独的DBHelper子类,如:

public class DBHelper extends SQLiteAssetHelper {

    private static final String DB_NAME = "...";
    private static final int DB_VERSION = 1;
    private static final String DB_STORAGE_DIR = "...";

    private static SQLiteDatabase db = null;
    private static DBHelper instance;

    // Create the db storage directory if it does not exist
    static {
        File dir = new File(DB_STORAGE_DIR);
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                Log.e("BEEP", "Create database folder failed! BANG!");
            }
        }
    }

    public static DBHelper getInstance(Context context){
        if(instance == null){
            instance = new DBHelper(context);
        }
        return instance;
//        return new DBHelper(context);
    }

    private DBHelper(Context context) {
        super(context, DB_NAME, DB_STORAGE_DIR, null, DB_VERSION);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        super.onUpgrade(db, oldVersion, newVersion);
    }

    public Cursor rawQuery(String query, String[] arguments){
        if(db == null || !db.isOpen()) {
            db = getReadableDatabase();
        }
        return db.rawQuery(query, arguments);
    }

    public void execute(String sql, Object[] arguments){
        if(db == null || db.isReadOnly()) {
            db = getWritableDatabase();
        }
        db.execSQL(sql, arguments);
    }

    public void close(){
        if(db != null && db.isOpen()){
            db.close();
        }
    }
}

我得到了DBHelper实例的两个引用,让我们说readInstance和writeInstance具有相同的上下文,我运行一些sql,如:

writeInstance.read(...);
for (int i = 0; i < n; i++) {
    readInstance.read(...);
    writeInstance.write(...);    //IllegalStateException 
}

然后我在write方法中得到了IllegalStateException,它在DBHelper.execute方法中。 我尝试在execute方法中同步db:

public void execute(String sql, Object[] arguments){
    if(db == null || db.isReadOnly()) {
        db = getWritableDatabase();
    }
    synchronized (db){
        db.execSQL(sql, arguments);
    }
}

但仍然收到错误。 任何建议都会有所帮助,谢谢!

1 个答案:

答案 0 :(得分:1)

发现了什么: 我没有在execute方法中检查isOpen状态,即使关闭了db,isReadOnly方法仍然返回false,所以在我以前的代码中,我在execute方法中使用了一个封闭的db。

<强> FIX:

public void execute(String sql, Object[] arguments){
    if(db == null || !db.isOpen() || db.isReadOnly()) {
        db = getWritableDatabase();
    }
    db.execSQL(sql, arguments);
}