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

Pil*_*pel 4 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
}
Run Code Online (Sandbox Code Playgroud)

这提出了两个问题

  1. 我做得对吗?(可能不是)
  2. 需要关闭一个SQLiteDatabase对象,如果不能在onDestroy方法?

编辑: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;

    ...
Run Code Online (Sandbox Code Playgroud)

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

//get database helper
        if(_databaseHelper == null)
            _databaseHelper = SalaryDatabaseHelper.getInstance(this);
Run Code Online (Sandbox Code Playgroud)

db初始化为AsyncTask.doInBackground():

protected Boolean doInBackground(Integer... data)
{
    try {
        //get writable database
        if(db == null)
            db = SalaryDatabaseHelper.getDbInstance();
Run Code Online (Sandbox Code Playgroud)

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

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;
    }

    ...
Run Code Online (Sandbox Code Playgroud)

Com*_*are 6

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

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

没有.

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

决不.SQLite是事务性的.无法关闭数据库没有风险.

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

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