ormlite-android icon indicating copy to clipboard operation
ormlite-android copied to clipboard

OrmLite Loaders and database connection loss at configuration changes

Open VincentJousse opened this issue 11 years ago • 12 comments

Hi,

I'm facing a database connection issue after configuration changes. I'm using a single activity which extends OrmLiteBaseActivity. I also use an OrmLiteQueryForAllLoader in this activity to load my persisted objects. At configuration changes, the activity is destroyed, so the database helper close the database connection since nobody use it anymore. Then the activity is recreated, leading to a new database connection. The problem is that OrmLiteQueryForAllLoader (which is kept alive even at configuration changes) retains a Dao object with the first created dabase connection. After a configuration change, this connection is closed and this leads to a IllegalStateException since the retained Dao tries to use a closed connection.

We need a way to keep the connection opened even when all activities are destroyed, maybe by retaining it in the loaders ?

VincentJousse avatar Oct 06 '14 15:10 VincentJousse

So it is static or something? Is there no way to detect the application is starting and specifically clear it or re-create it?

j256 avatar Oct 06 '14 17:10 j256

You're thinking about a workaround in my application code, right ?

My point of view is that the use case I describe is really simple : one activity which uses one loader. That's it. This use case should work with OrmLite loaders because it is the simpliest use case we can imagine for loaders use ! Android Loaders are designed to load data regardless of activities life cycle, partly to not reload data at each configuration change. When OrmLite Loaders depend on activities life cycle because of the database connection management, they don't comply with android loaders "contract".

So I think the best solution is to find a correction in the OrmLite library code itself. As I said before, the solution may be to make the OrmLite loaders retain the database connection. What do you think of this ?

VincentJousse avatar Oct 06 '14 21:10 VincentJousse

I don't think you should retain the database connection. I don't think that's proper. Can you find some Android docs which say otherwise?

j256 avatar Oct 07 '14 15:10 j256

When I say "retain the database connection", I mean "call OpenHelperManager.getHelper and OpenHelperManager.releaseHelper". The Android docs http://developer.android.com/guide/components/loaders.html and http://developer.android.com/reference/android/content/Loader.html don't mention anything about database because Loaders mecanism abstracts the data source. What other than mine solution would you propose to solve the database connection issue ?

VincentJousse avatar Oct 08 '14 14:10 VincentJousse

@j256 Do you agree that OrmLite must be compliante with the use case I described ?

VincentJousse avatar Oct 15 '14 21:10 VincentJousse

I think your application must be compliant. I'm not sure I agree that it's ORMLite responsibility to protect against it. This is the first time that I've heard of this problem. Feel free to take a poll on the android mailing list however.

j256 avatar Oct 16 '14 13:10 j256

To be 100% clear on this. You can, and should, keep your db connection open. I wrote the original version of the base activities that open/close the db connection, and have since done a lot of research and testing on this. You should keep a singleton pointing at a single open helper instance.

See: http://stackoverflow.com/a/3689883 And: http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection And (more formally): http://stackoverflow.com/a/12715032

You are correct. I imagine if your db is closed on rotate, your loader is going to freak out if its holding onto Dao. If you're going to change things, though, you'll need to change ALL of your base classes. The key to good DB health is one OpenHelper instance.

I just realized how old this bug was, but its probably good reading if somebody else is having the issue.

This also improves my argument to deprecate the helper activities ;)

kpgalligan avatar Jan 30 '15 03:01 kpgalligan

OK, I understand. The problem here is that the documentation encourage to do what I did, I mean use OrmLiteBase classes to manage access to the database helper whereas it seems that it is not the right way to go. So I agree, the helper activities may be deprecated and the documentation updated to explain the good way of doing (using a subclass of OrmLiteSqliteOpenHelper as singleton ?).

VincentJousse avatar Feb 19 '15 10:02 VincentJousse

I'm with you. I have another potential solution, but I'm reluctant to put more work into the helper classes. Its sort of complex to explain, unless you have a deep understanding of Android threading. Essentially, queue the closing call in the helper on the main thread, so by the time it gets there, if you did a rotate, the new activity would've incremented the db counter, and it won't close. TBD.

kpgalligan avatar Feb 19 '15 17:02 kpgalligan

It's becoming quite complicated !! Why not letting OrmLite Loaders be connected to OpenHelperManager like OrmLite Activities are ? The dao parameter in constructor would be replaced by a class parameter to let them call getDao() on the database helper (obtained thanks to the OpenHelperManager) and manage their own dao instance ?

VincentJousse avatar Feb 19 '15 20:02 VincentJousse

@kpgalligan , what about initializing the singleton in Application.onCreate() ? This would permit to remove the context parameter in the singleton getInstance() function (which is only used for initialization).

VincentJousse avatar Mar 02 '15 12:03 VincentJousse

@kpgalligan , what do you think of my previous proposals ?

VincentJousse avatar May 28 '15 20:05 VincentJousse