问题描述
我几个小时都不断收到这个令人讨厌的运行时错误,这使我的应用程序崩溃了:
I kept getting this annoying runtime error for hours, which crashed my app:
由以下原因引起:java.lang.IllegalStateException:尝试重新打开一个已经关闭的对象:SQLiteDatabase
Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase
经过一些调试后,我发现发生这种情况是因为我在 onDestory()
方法中关闭了SQLiteDatabse对象.当我同时调用 SQLiteOpenHelper.close()
时,就会发生这种情况.
After some debugging I found that it happens because I close my SQLiteDatabse object, in the onDestory()
method. It happens when I call SQLiteOpenHelper.close()
as well.
@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
}
这提出了两个问题
- 我做对了吗?(可能不是)
- 如果不在
onDestroy
方法中,我何时 需要关闭SQLiteDatabase对象?
- Am I doing it right? (probably not)
- When do I need to close a SQLiteDatabase object, if not in the
onDestroy
method?
DB和Helper类是静态的:
The DB and the Helper classes are static:
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:
I initialize _databaseHelper in the onCreate() method:
//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();
我对帮助器类和数据库类使用单例:(均通过帮助器类访问)
I use singletons for the helper class and the database class: (both accessed via the helper class)
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;
}
...
推荐答案
您的 SQLiteOpenHelper
instance 是 static
,因此在范围上是全局的.考虑到这一点:
Your SQLiteOpenHelper
instance is static
, and therefore global in scope. With that in mind:
否.
从不.SQLite是事务性的.关闭数据库没有任何风险.
Never. SQLite is transactional. There is no risk from failing to close the database.
在更简单的方案中,只有一个具有数据库访问权限的组件,您可以在销毁该组件时将其关闭.在您的情况下,您的整个应用程序(包括后台线程)都可以访问数据库.在这种情况下,您永远不会关闭它.
In simpler scenarios, where there is a single component with access to the database, you might close it when that component is destroyed. In your case, your whole app, including background threads, have access to the database. In that case, you simply never close it.
这篇关于什么时候应该关闭SQLiteDatabase对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!