1

So I have two contexts (service and UI activity) running from the same process, and also I use traditional's wrapped way to get write handle:

package me.soexample.sobad;
import java.util.concurrent.atomic.AtomicInteger;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DatabaseManager {

    private static AtomicInteger mOpenCounter = new AtomicInteger();

    private static DatabaseManager instance;
    private static DatabaseHelper mDatabaseHelper;
    private SQLiteDatabase mDatabase;

    public static synchronized void initializeInstance(DatabaseHelper helper) {
        if (instance == null) {
            instance = new DatabaseManager();
            mDatabaseHelper = helper;
        }
    }

    public static synchronized DatabaseManager getInstance() {
        if (instance == null) {
            throw new IllegalStateException(DatabaseManager.class.getSimpleName() +
                    " is not initialized, call initializeInstance(..) method first.");
        }

        return instance;
    }



    public SQLiteDatabase openDatabase() {
        if(mOpenCounter.incrementAndGet() == 1) {
            // Opening new database
            mDatabase = mDatabaseHelper.getWritableDatabaseAlt();
        }
        return mDatabase;
    }

    public void closeDatabase() {
        if(mOpenCounter.decrementAndGet() == 0) {
            // Closing database
            mDatabase.close();

        }
    }
}

As if it can not be expected, it often results in:

04-11 04:24:51.738: E/gsmspy(24331): java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /storage/sdcard0/my.db
04-11 04:24:51.738: E/gsmspy(24331):    at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
04-11 04:24:51.738: E/gsmspy(24331):    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1310)
04-11 04:24:51.738: E/gsmspy(24331):    at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253)
04-11 04:24:51.738: E/gsmspy(24331):    at me.soexample.sogood.somethod2(sogood.java:51)
04-11 04:24:51.738: E/gsmspy(24331):    at me.soexample.sogood.somethod(sogood.java:41)

As you can see, there are no references to DatabaseManager; so it seems to be a multithreading problem. Now, what do I do to have a guaranteed ability to write to DB object returned from such wrapper?

kagali-san
  • 2,646
  • 6
  • 40
  • 84

1 Answers1

0

The original (see "Approach #2") class was more of smart something. Now, a DatabaseHelper (SQLiteOpenHelper) is constructed in DatabaseManager(), removing the problem (no more two SQLiteOpenHelper's working in parallel worst-case)

Community
  • 1
  • 1
kagali-san
  • 2,646
  • 6
  • 40
  • 84
  • For the users that doesn't use the SQLiteOpenHelper, can solve the problem using this: http://stackoverflow.com/questions/30058274/multiple-connections-to-sqlite-with-simultaneous-async-tasks!! Good programming! :) – Merlí Escarpenter Pérez Jul 17 '15 at 07:50