Android数据库 – 由于连接池已关闭,无法执行此操作

我有android数据库和游标的奇怪问题。 不时(非常罕见)发生,我收到客户的崩溃报告。 很难找出崩溃的原因,因为我有大约150,000个活跃用户,每周大约有1个报告,所以这真的是一个小错误。 这是例外:

STACK_TRACE=java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed. at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962) at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599) at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348) at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894) at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834) at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62) at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:144) at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133) at sk.mildev84.agendareminder.aca(SourceFile:169) 

在每个游标“迭代和探索”之前,我使用此代码确保一切正常:

 db = instance.getWritableDatabase(); cursor = db.rawQuery(selectQuery, null); if (isCursorEmptyOrNotPrepared(cursor)) { ... } private synchronized boolean isCursorEmptyOrNotPrepared(Cursor cursor) { if (cursor == null) return true; if (cursor.isClosed()) return true; if (cursor.getCount() == 0) // HERE IT CRASHES return true; return false; } 

它符合要求:

 if (cursor.getCount() == 0) 

谁知道为什么? 我想,我正在检查所有可能的例外情况和条件……为什么我的应用程序崩溃了?

PS:所有数据库方法都是同步的,我在所有情况下都正确地打开和关闭数据库/游标,我多次检查它。

问题
如果在关闭数据库后尝试另一个操作,它将为您提供该exception。因为db.close(); 释放对该对象的引用,如果最后一个引用被释放则关闭该对象。


在静态上下文中保留单个SQLiteOpenHelper实例( Singleton )。 进行延迟初始化,并synchronize该方法。 如

 public class DatabaseHelper { private static DatabaseHelper instance; public static synchronized DatabaseHelper getInstance(Context context) { if (instance == null) instance = new DatabaseHelper(context); return instance; } //Other stuff... } 

你不必关闭它? 当应用程序关闭时,它会释放文件引用,如果它甚至坚持它
即你不应该关闭数据库,因为它将在下一次调用中再次使用。 所以只需删除

 db.close(); 

有关详细信息,请参阅Single SQLite连接

你只需删除删除db.close()

我也有这个问题。 我的SQLiteOpenHelper类是Singleton,也是在每次CRUD操作后关闭数据库。 在我的SQLiteOpenHelper类中使我的方法(CRUD)同步之后,我再也没有得到错误了:)

同样的问题发生在我身上,所以在阅读解释后我删除了
db.close();

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

public int delete(Uri uri, String selection, String[] selectionArgs)
ContentProvider的方法
不需要db.close(),因为ContentProvider本身负责关闭数据库。

问题很明显

SQLiteCursor无法执行’getCount’操作,因为连接池已关闭

为了避免IllegalStateException,如果合适,我们可以始终保持数据库打开。 在其他情况下,我们需要在尝试getCount之前检查状态

我的经验如下:

有缺陷的代码:

 SOLiteOpenHelper helper = new SOLiteOpenHelper(context); SQLiteDatabase db = helper.getWritableDatabase(); Cursor cursor = db.query(...); if (cursor != null) { cursor.getCount(); // HERE IT CRASHES } 

完美代码:

 SOLiteOpenHelper helper = new SOLiteOpenHelper(context); SQLiteDatabase db = helper.getWritableDatabase(); Cursor cursor = db.query(...); if (cursor != null && db.isOpen()) { cursor.getCount(); // OK! }