0

Short version: what is the best practice way to access the same DB from both activity and from started service?

Long version: I have a case where I start persistent service from activity. Service is populating the DB with data while activity is displaying it on screen. Neither of them is running all the time - service can run when there is no activity, and activity can run when service is not started yet. But service can only be stopped from activity (it never stops itself).

I am using subclass of SQLiteOpenHelper to access the DB. The problem I tripped over is that apparently closing DB in one SQLiteOpenHelper instance closes it in another too.

I can think of these options:

  1. singleton pattern (single SQLiteDatabase instance in a public static var - only activity can close it (because it knows if the service is running or not)) - ugly
  2. check if service/activity is running before closing it in the other one - ugly
  3. build acquire/release into SQLiteOpenHelper's getReadableDatabase()/close()

I would go with 3., but this must be a very common pattern, so I'm wondering if there is such a built-in mechanism in place already - I'd hate to reinvent the wheel.

In other words, what would be the proper way to do it?

johndodo
  • 17,247
  • 15
  • 96
  • 113

2 Answers2

1

The usual paradigm for any database on Android is to have one provider open the database and handle requests as intents. This has the advantage of serializing requests.

Opening databases from different code is completely non-standard.

If you really need an app to notice each time something is added, a broadcast intent from the provider might be the answer.

Renate
  • 761
  • 4
  • 11
  • In this case service is gathering the data and activity is displaying it (in a graph). Note that activity might not be running when service is gathering data - and later it has to show data history for period when it was paused. I could get around these limitations, but in this case it would make application much more complex. – johndodo May 30 '12 at 17:00
  • After further thought I am starting to like your idea... I have solved the problem with third option, but I will refactor my app to use broadcast intents (instead of repeating DB reads). Thank you and +1 to you Sir. ;) – johndodo May 31 '12 at 19:42
0

I have solved the problem using retain/release counter:

public class DBHandler extends SQLiteOpenHelper
{
    private static int retainCount = 0;

    @Override
    public synchronized SQLiteDatabase getReadableDatabase()
    {
        DBHandler.retainCount++;
        return super.getReadableDatabase();
    }
    @Override
    public synchronized SQLiteDatabase getWritableDatabase()
    {
        DBHandler.retainCount++;
        return super.getWritableDatabase();
    }
    @Override
    public synchronized void close()
    {
        DBHandler.retainCount--;
        if (DBHandler.retainCount == 0)
            super.close();
        }
    }
}
johndodo
  • 17,247
  • 15
  • 96
  • 113