I met this problem when I query database from multi-theads environment. Since the getWritableDatabase() return same SQLiteDatabase object for the same SQLiteOpenHelper, if you closed it in one thread while another thread using it, it will cause the SQLiteConnectionPool close exception. I analysied it for my case here: java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
Here is the suggestions for your code:
Judged from you code that it may exists in the SQLiteOpenHelper object. You need to make it singleton since one SQLiteOpenHelper is mapped to one db. It is not necessary to keep too many SQLiteOpenHelper object in one project for one db. You may make it like this:
// the PalmDB is your Helper name
class PalmDB extends SQLiteOpenHelper {
private static PalmDB sInstance = null;
public static PalmDB getInstance(final Context context){
if (sInstance == null){
synchronized (SQLiteOpenHelper.class) {
if (sInstance == null) {
// be sure to call getApplicationContext() to avoid memory leak
sInstance = new PalmDB(context.getApplicationContext());
}
}
}
return sInstance;
}
// ... next is the code for your insert method:
protected SQLiteDatabase getDatabase() {
OpenHelperManager.requireConnection();
return getWritableDatabase();
}
protected void closeDatabase() {
OpenHelperManager.releaseHelper(this);
}
/*
* Note that in this method, I didn't call getWriteDatabse() and SQLiteDatabase.close()
* to open and close db connection, instead I used two methods and added some options there.
*/
public synchronized void insert(int deviceid, int productid) {
SQLiteDatabase sqLiteDatabase = getDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("deviceid", deviceid);
contentValues.put("productid", productid);
sqLiteDatabase.insert(payment_table, null, contentValues);
closeDatabase();
}
}
Next is the class used in SQLiteOpenHelper:
public class OpenHelperManager {
@SuppressLint("StaticFieldLeak")
private static boolean isClosed = false;
private static int instanceCount = 0;
public static synchronized void releaseHelper(PalmDB helper) {
instanceCount--;
LogUtils.e(String.format("releasing helper %s, instance count = %s", helper, instanceCount));
if (instanceCount <= 0) {
if (helper != null) {
LogUtils.e(String.format("zero instances, closing helper %s", helper));
helper.close();
isClosed = true;
}
if (instanceCount < 0) {
LogUtils.e(String.format("too many calls to release helper, instance count = %s", instanceCount));
}
}
}
public static synchronized void requireConnection() {
isClosed = false;
instanceCount++;
}
public static boolean isClosed() {
return isClosed;
}
}
Here I used the static and sychronized methods to lock the method, and added calculations in each method. When the getWriteableDatabse() method is called, I will increase the number of connection, otherwise I decrease it. When the connections count is 0, I close the Databse connection pool. I think it may be safe and also closed the connection. (Note that close the Helper class will also close the SQLiteDatabse object. You may refer to the source code.)
Hope it works!