Keeping Single Database Connection on Android - android

This question seems very similar to many I have read but then again, I did not find any code that would satisfy me. (or I am too sleepy to realize that)
I have a singleton database helper to ensure only one of them exists. The problem is not here. I encounter a problem when trying to ensure only one database connection exists while still using getReadableDatabase and getWritableDatabse methods.
I know it returns the same reference in most cases and I can handle use of it but I don't know what to do in case I have read-only connection open (probably was running out of memory) and another thread wants to open a writable connection. I would like to block the writing thread until read-only connection is closed and then attempt to open a writable connection.
How do you do that? That, probably, can be done in Java only with some thread locking but not sure which methods should be used.
P.S. In case I am missing something - feel free to show me how it should be done in another way.

I've gone through the same issues in the past and synchronization is the answer. Simply put, synchronize on the databasehelper instance.Or what you can do is create a wrapper method for getWritableDatabase and use the synchronized keyword in the method declatation. Then never call getReadableDatabase but just the wrapper method. Since getReadableDB and getWritableDB give the same reference, it's safe to do so. Make sense?

Related

SQLiteDatabase to close or not to close after using

When I look at examples from tutorials I see that for getReadableDatabase the db is not closed at the end but for getWritableDatabase it is always closed at the end. Why is that? Even the docs specify that I must call close on getWritableDatabase. I have read both docs, so please do not simple quote the docs to me. Thanks.
Despite what the documentation implies, there isn't really a relevant difference between getReadableDatabase() and getWritableDatabase(); both open the database, and that database stays open until it is close()d.
So those examples are not correct; they should handle both cases in the same way.
Please note that "when you no longer need the database" does not necessarily mean that you need to close it after each query; if, for example, an activity is likely to access the database multiple times, it is perfectly valid to open it when the activity is started, and to close it when the activity is stopped.
An open database connection reserves some memory for its cache, and the system stops activities if it needs more memory, so you should ensure that there is no open database when there is no active activity.
You need to keep the database open as long as there are cursors in use that contain data from it. I myself rarely close the database, even when using getWriteableDatabase().
As per android documentation sqlite database
Writable database "Once opened successfully, the database is cached, so you can call this method every time you need to write to the database. (Make sure to call close()when you no longer need the database.) Errors such as bad permissions or a full disk may cause this method to fail, but future attempts may succeed if the problem is fixed."
As the writable is cached as soon it's opened it means it will take up memory.
And if database is large then huge memory , so not closing it or keeping it open may lead to member leaks.
Hope this helps you :)

Clarifying When to Open and Close a DataSource

Ive done a lot of Googlig on this topic and I'm confused as to best practice.
Initially I had:
A) Created a DataBase object in my main class header area and then just passed it to functions as needed. I then later read that a DataBase should be opened and closed each time before use.
so then I:
B) went to each function (passing Context) which uses a SQL command and created a new DataBase object, created a filled cursor via SQL, and then closed the Database before returning. However, I then later read that it's expensive to do this.
now i'm thinking that:
C) I should create a new Database object in each subclass that uses one, and open and close it as needed.
Im sorry for the noob and seemingly design question (delete it if it's out of scope of StackOverflow), however, I truly am confused of how this should be handled to avoid errors, and how Google wants us to do it.
Regards
The Android docs recommend using an SQLiteOpenHelper, which caches the database object. From the SQLiteOpenHelper reference:
Once opened successfully, the database is cached, so you can call this
method every time you need to write to the database. (Make sure to
call close() when you no longer need the database.)
So, I'd go for a singleton carrying an instance of SQLiteOpenHelper, so you can access it from anywhere. Then get the database where you need it, and close it on exit points of your application (if any). That way you only open a database if required, but can re-use the same connection for other tasks as well.
If you do only need the database for single tasks and/or there are other Applications accessing the same database, you may consider closing it directly after your database-tasks are done; there is a discussion about closing in another question.

Android: release database connection

I was looking for a solution for making my slqite database, accessing syncronized and avoid problem with open/close connection, and I falled in this good answer:
In this solution, however, there is not a explicit closing of database.
many argue that this is not a problem, but I would know how can I close the connection after the application is stopped.
note: In the aforementioned link the author of the answer suggest this:
With my implementation the singleton lives for the life of the
application. Therefore I did not implement an explicit destructor,
instead, in the app shutdown code (or crash handler) the database is
explicitly closed. See Thread.setDefaultUncaughtExceptionHandler()
which I used in ApplicationContext.onCreate() after I posted my sample
code.
Can be this a good solution? If yes, how can I manage Thread.setDefaultUncaughtExceptionHandler() ?
EDIT:
I want also, that if the database resource is not available, the requiring thread will wait until the database is released. Can I use this code? the isDbLockedByOtherThreads() is deprecated
private myDatabase(){
final DbHelper mDbHelper =new DbHelper(ApplicationFramework.getContext());
mDB = mDbHelper.getWritableDatabase();
while(mDB.isDbLockedByCurrentThread() || mDB.isDbLockedByOtherThreads()) {
//db is locked, keep looping
}
}
You need not to worry about closing database connection after the application is stopped it automatically gets closed.
Actually there is only one connection internally, you make its different instance thats a different thing. Thats why many people says closing of database connection does'nt make any sense.
Always have a single static object of database connection it will be safe and less exception prone, and don't worry about closing it.
If you try to write to the database from actual distinct connections at the same time, one will deifnately get failed . It will not wait till the first is done and then write. It will simply not write your change. Worse, if you don’t call the right version of insert/update on the SQLiteDatabase, you won’t get an exception. You’ll just get a message in your LogCat, and that will be it.
Answer for updated query
Use only Single static instance of your db connection no need to make others threads, all operations will be automatically synchronised.

When should I call close() on SQLiteOpenHelper used by ContentProvider

In my android app, I use SQLiteOpenHelper to implements ContentProvider.
Query, add, delete operations are all through ContentProvider.
But in one of my android phone(htc g13), I found *.db-wal file in directory /data/data/[package name]/databases. And the file size increate very fast when operating with ContentProvider. It occupied user RAM space too much.
It is recommended to close the SQLiteOpenHelper to solve my problem (it is useful) in post enter link description here.
But I want to find a "place" to add the "close()" method since I am not using SQLiteOpenHelper directly (using through ContentProvider). query() method in ContentProvider must return a Cursor, and SQLiteDatabse should stay in open state.
I'm confused, what show I do now to keep *.db-wal gone and use ContentProvider normally?
Android framework engineer defer to this view that you need to close the DB.
As per Dianne Hackborn(Android Framework Engineer) in this thread:
A content provider is created when its hosting process is created, and
remains around for as long as the process does, so there is no need to
close the database -- it will get closed as part of the kernel
cleaning up the process's resources when the process is killed.
You have a couple of cases to cover:
1) When your application finishes (e.g. entering onDestroy()) make sure you close all Cursors, Database instances of SQLiteDatabase and SQLiteOpenHelpers (using the model if (connection.isOpen()) object.close())
2) When you application goes onPause() -> onResume() - use this stages appropriately to pause/resume your connection or to close/open them.
It's a good practice to close your database immediately after you finish working with it. The database is cached, so there's no problem closing it and re-acquire instance again when you need it with getWritableDatabase()/getReadableDatabase()
From the official doc:
"Once opened successfully, the database is cached, so you can call this method every time you need to write to the database. (Make sure to call close() when you no longer need the database.)"
Also keep in mind that if SQLiteOpenHelper caches and tracks all open instances of SQLiteDatabase, it basically means that if you don't leave open database connections, you won't have to call close on SQLiteOpenHelper.
I recommend closing all cursors and databases immediately after you stop working with them. Always try to enforce try/catch/ for queries operations and a "finally block" to call the close methods on the objects.

Closing an SQLite database on one thread breaks the database opened on another thread

We all learn that resources, such as database connections, should be acquired late and released early.
Yet applying this principle to SQLite database connections on Android have caused me some headache.
I have an app that download updates from a backend server in a service working in the background, writing updates to the database at a regular basis. The problem I experience arise when the following sequence occurs:
Service opens a writable database connection
Some activity opens a readable database connection
Service closes its database connection concurrently with the activity reading data
Activity fails due to its database connection was closed
Both the service and the activity uses the same SQLiteOpenHelper class, though different instances, to open their connections. My initial assumption was that this should work just fine, but somehow it seems that the underlying connection is shared between the two database instances.
To work around the problem I ended up not closing the database objects, only closing any opened cursors. This seems to work, though I'm not sure that I'm not leaking memory here.
Is there something obvious I am missing here?
Is there something obvious I am missing here?
I'd say no. Looking at the source code to SQLiteOpenHelper, I can't see how two instances could be sharing a SQLiteDatabase object.
Some diagnostic suggestions:
Dump the toString() value of each SQLiteDatabase, which should give you a Java instance ID. If they are the same, that is where your problem lies, and you will need to work your way upstream to figure out how the heck this is happening (e.g., you really are using the same instance of the SQLiteOpenHelper).
With your database in a stable state (i.e., no need to create or upgrade), flip one of your two database spots to use SQLiteDatabase directly, rather than via SQLiteOpenHelper, and see if that changes matters.

Categories

Resources