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

时间:2014-04-30 11:54:11

标签: android database android-cursor

我有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.a.c.a(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:所有数据库方法都是同步的,我在所有情况下都正确地打开和关闭数据库/游标,我多次检查过。

5 个答案:

答案 0 :(得分:27)

<强>问题
如果在关闭数据库后尝试其他操作,它将为您提供该异常。因为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 connection

答案 1 :(得分:0)

你刚删除 删除db.close()

答案 2 :(得分:0)

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

答案 3 :(得分:0)

同样的问题发生在我身上,所以在阅读explanation后我删除了        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本身负责关闭数据库。

答案 4 :(得分:0)

问题很清楚

  

SQLiteCursor无法执行&#39; getCount&#39;操作,因为连接池已关闭

为避免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!
}