Android:无法执行此操作,因为连接池已关闭

2022-08-31 14:31:43

我正在阅读StackOverflow关于这个问题,我仍然没有找到解决方案。我注意到有时,我的应用程序会抛出此错误:

   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)
        ...

我有一个名为使用此方法的文件来获取它的实例:DatabaseHelper.java

public static DatabaseHelper getInstance(Context context) {
    if (mInstance == null) {
        mInstance = new DatabaseHelper(context.getApplicationContext());
    }
    return mInstance;
}

然后我有这样的方法(它在带有该错误的行中崩溃)。它几乎从不崩溃,但有时它确实如此。cursor.moveToFirst()

public Profile getProfile(long id) {
    SQLiteDatabase db = this.getReadableDatabase();

    String selectQuery = "SELECT * FROM " + TABLE_PROFILES + " WHERE " + KEY_PROFILES_ID + " = " + id;
    Cursor cursor = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    Profile profile = new Profile();
    if (cursor.moveToFirst()) {
        doWhatEver();
    }
    cursor.close();
    db.close();

    return profile;
}

就是这样,在我使用的所有方法中:

SQLiteDatabase db = this.getReadableDatabase(); (or Writable)

然后我关闭光标和数据库。在本例中,错误被扔到行中:

cursor.moveToFirst();

我不明白为什么错误说db关闭,如果我之前正在调用。请支持!谢谢:)this.getReadableDatabase()


答案 1

删除

db.close();

如果在关闭数据库后尝试其他操作,它将为您提供该异常。

文档说:

释放对对象的引用,关闭对象...

另外,请查看 Android SQLite 关闭的异常,该异常涉及来自 Android 框架工程师的评论,该注释指出没有必要关闭数据库连接,但是仅当在 .ContentProvider


答案 2

我目前有同样的问题。在删除为我解决问题的同时,我认为该问题是由多线程引起的。这是我的研究。db.close()

SQLiteOpenHelper持有对 的引用,当 或 调用时,它将返回该引用,如果 关闭或为 null,则将创建一个新对象。请注意,在 get 方法中,代码在同步块中受到保护。SQLiteDatabasegetReadableDatabase()getWritableDatabase()SQLiteDatabaseSQLiteDatabase

SQLiteDatabase是 的子类。 实现引用计数方案。SQLiteClosableSQLiteClosable

  • 首次创建时,计数为 1。

  • 当数据库操作方法运行时(如插入、查询),它将增加计数,并在方法结束时减少计数。但是游标操作不受引用计数的保护。

  • 如果计数减少到 0,则将关闭连接池,并将成员对象设置为 null,现在将关闭SQLiteConnectionPoolSQLiteDatabase;

  • SQLiteDatabase.close()将计数减少 1;

因此,如果您有一个单线程方案,关闭将很好,因为只需重新创建它即可。SQLiteDatabaseSQLiteOpenHelper

如果您执行多线程操作,那么您将遇到麻烦。假设线程 A 和线程 B 都调用 ,并返回它所持有的 SQLiteDatabase,然后线程 A 首先完成其操作和调用,现在对象线程 B 已关闭,因此任何后续的 db 操作调用或 cursor 方法调用都将引发异常。getReadableDatabase()SQLiteOpenHelperSQLiteDatabase.close()SQLiteDatabase


推荐