I have one database helper class and three datasource classes for three tables in same database.
The database is accessed in lots of places via AsyncTasks. I faced this "attempt to reopen an already-closed object..." problem, I searched around and found that dbhelper.getReadableDatabase()
returns same object for already opened connection. I guessed that problem must be due to when two threads performing operations simultaneously and one of them finishes its task and calls close()
the connection gets closed and running thread throws this exception.
So to avoid close()
I wrote following two methods:
public static synchronized void newOpenRequest() {
requestsOpen++;
Util.debuglog(TAG, "Open requests: " + requestsOpen);
}
public static synchronized boolean canClose() {
requestsOpen--;
Util.debuglog(TAG, "Open requests: " + requestsOpen);
if(requestsOpen == 0)
return true;
return false;
}
In all of three datasource classes, when I do it in following manner:
private void openRead() {
database = dbhelper.getReadableDatabase();
DBHelper.newOpenRequest();
Log.i(TAG, "Database opened.");
}
private void openWrite() {
database = dbhelper.getWritableDatabase();
DBHelper.newOpenRequest();
Log.i(TAG, "Database opened.");
}
private void close() {
if (DBHelper.canClose()) {
dbhelper.close();
Util.debuglog(TAG, "Database closed.");
}
}
My LogCat output is as follows:
So as highlighted in black rectangle, total openRequests
were 0, so database closed, normal but as highlighted in red rectangle,
firstly openRequests
were 0, so that time only database was supposed to get closed, but (my guess) what happened is canClose()
returned true for a thread, and just before call to dbhelper.close();
another thread called open()
(since openRequests = 1 is on LogCat just before close) and then first thread's close()
invoked giving trouble to another running thread.
So looking for solution to avoid this concurrent access problem. Thank you.