Android database - Cannot perform this operation because the connection pool has been closed
Asked Answered
B

5

15

I have strange problem with android database and cursors. Time to time (very rarely) happens, that I got crash report from customers. It's hard to find out why it crashes, as I have ~ 150 000 active users and maybe 1 report per week or so, so it's really some minor bug. Here is exception:

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)

Before every cursor "iterating and exploring" I use this code to make sure everything is ok:

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

And it falls at line:

if (cursor.getCount() == 0)

Anyone know why? I think, I am checking all possible exceptions and conditions...Why is my app crashing here?

PS: All database methods are synchronized and I am correctly opening and closing database/cursors in all cases, I checked it many times.

Bedrock answered 30/4, 2014 at 11:54 Comment(4)
Post more code and full stacktrace. You get this excpetion -> you have a mistake somewhereJeanicejeanie
There is no need to close the db. Android handle it. Read this Great explanation here...#14002522Abreact
@Nepster I wonder if that applies only to Content ProvidersSonometer
Please how did you manage to solve this error? kindly let me know if @GuriBhai solution owrked for you. I'm having the same error but closing the db did not solve my problem.Mountaineering
C
29

Problem
If you try another operation after closing the database, it will give you that exception.Because db.close(); releases a reference to the object, closing the object if the last reference was released.

Solution
Keep a single SQLiteOpenHelper instance(Singleton) in a static context. Do lazy initialization, and synchronize that method. Such as

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

And you don't have to close it? When the app shuts down, it’ll let go of the file reference, if its even holding on to it.
i.e. You should not close the DB since it will be used again in the next call. So Just remove

db.close();

For more info See at Single SQLite connection

Coprolite answered 13/6, 2014 at 8:55 Comment(0)
B
1

The problem is clear that

SQLiteCursor cannot perform 'getCount' operation because the connection pool has been closed

To avoid IllegalStateException, we may keep the database open all the time if that is appropriate. In other situations we need to check the status before trying getCount.

My experience is as follows:

Defective Code:

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

Perfect Code:

SOLiteOpenHelper helper = new SOLiteOpenHelper(context);
SQLiteDatabase db = helper.getWritableDatabase();
Cursor cursor = db.query(...);
if (cursor != null && db.isOpen()) {
    cursor.getCount(); // OK!
}
Boehmenism answered 24/3, 2018 at 3:56 Comment(0)
S
0

You just remove Remove db.close()

Stork answered 30/4, 2014 at 11:54 Comment(0)
S
0

I had this problem too. my SQLiteOpenHelper class was Singleton as well as closing the db after each CRUD operation. After I make my methods(CRUD) synchronized in my SQLiteOpenHelper class, I didn't get error any more :)

Stuckey answered 16/4, 2015 at 9:5 Comment(0)
M
0

Same problem occured to me, so after reading explanation I removed
db.close();
from
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
and
public int delete(Uri uri, String selection, String[] selectionArgs)
method of ContentProvider
No need of db.close() as ContentProvider itself take care of closing of database.

Melanoma answered 22/10, 2015 at 19:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.