Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OrmLite Loaders and database connection loss at configuration changes #30

Open
VincentJousse opened this issue Oct 6, 2014 · 12 comments

Comments

@VincentJousse
Copy link

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 ?

@j256
Copy link
Owner

j256 commented Oct 6, 2014

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

@VincentJousse
Copy link
Author

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 ?

@j256
Copy link
Owner

j256 commented Oct 7, 2014

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?

@VincentJousse
Copy link
Author

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
Copy link
Author

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

@j256
Copy link
Owner

j256 commented Oct 16, 2014

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.

@kpgalligan
Copy link
Collaborator

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 ;)

@VincentJousse
Copy link
Author

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 ?).

@kpgalligan
Copy link
Collaborator

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.

@VincentJousse
Copy link
Author

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
Copy link
Author

@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
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants