我什么时候应该关闭一个SQLiteDatabase对象?

时间:2017-06-15 22:25:36

标签: android

我持续数小时遇到这个令人讨厌的运行时错误,这使我的应用程序崩溃了:

  

java.lang.RuntimeException:执行时发生错误   doInBackground()。

     

引起:java.lang.IllegalStateException:尝试   重新打开一个已经关闭的对象:SQLiteDatabase

经过一些调试后,我发现它发生了,因为我在onDestory()方法中关闭了我的SQLiteDatabse对象。当我拨打SQLiteOpenHelper.close()时也会发生这种情况。

@Override
protected void onDestroy() {
    super.onDestroy();
    _cursor.close(); //is fine
    _db.close(); //causes error
    _databaseHelper.close(); //causes error too (probably calls db.close() internally..?)
    SharedFunctions.d("closed!"); //ignore this ugly thing
}

这提出了两个问题

  1. 我做得对吗? (可能不是)
  2. 需要关闭SQLiteDatabase对象时,如果不是onDestroy方法吗?
  3. 编辑: DB和Helper类是静态的:

    public class MainActivity extends Activity {
    
        private Cursor _cursor = null;
        private MyCursorAdapter _myCursorAdapter = null;
        private ListView _listView = null;
    
        private static SalaryDatabaseHelper _databaseHelper = null;
        public static SQLiteDatabase db = null;
    
        ...
    

    我在onCreate()方法中初始化_databaseHelper:

    //get database helper
            if(_databaseHelper == null)
                _databaseHelper = SalaryDatabaseHelper.getInstance(this);
    

    db已在AsyncTask.doInBackground()

    中初始化
    protected Boolean doInBackground(Integer... data)
    {
        try {
            //get writable database
            if(db == null)
                db = SalaryDatabaseHelper.getDbInstance();
    

    我使用单例作为辅助类和数据库类:(都通过辅助类访问)

    class MyDatabaseHelper extends SQLiteOpenHelper{
    
        private static SalaryDatabaseHelper _instance = null;
        private static SQLiteDatabase _dbInstance = null;
    
        //singletons
        public static synchronized SalaryDatabaseHelper getInstance(Context context)
        {
            // Use the application context, which will ensure that you
            // don't accidentally leak an Activity's context.
            if (_instance == null)
                _instance = new SalaryDatabaseHelper(context.getApplicationContext());
    
            return _instance;
        }
    
        public static synchronized SQLiteDatabase getDbInstance() {
            if(_dbInstance == null)
                _dbInstance = _instance.getWritableDatabase();
    
            return _dbInstance;
        }
    
        ...
    

2 个答案:

答案 0 :(得分:6)

您的SQLiteOpenHelper 实例static,因此范围为全局。考虑到这一点:

  

我做得对吗? (可能不是)

没有

  

我什么时候需要关闭SQLiteDatabase对象,如果不是在onDestroy方法中?

从不。 SQLite是事务性的。没有关闭数据库的风险。

是的,这也让我感到烦恼,但我已经经历了七个悲伤的阶段,我正在接受“接受”

在更简单的场景中,只有一个组件可以访问数据库,您可以在销毁该组件时将其关闭。在您的情况下,您的整个应用程序(包括后台线程)都可以访问数据库。在这种情况下,你根本就不会关闭它。

答案 1 :(得分:2)

实际上,您不必关闭数据库连接。 您可以将数据库保存为Application对象中的字段。

官方文档没有说明数据库关闭的时间。此外,this question引用了Google工程师的旧帖子(现已删除)  这说明这种做法没问题。

在实际应用中,它运作良好多年。