android sqlite database already closed error - android

I have an app with a sqlite database.
I created my own database class that holds an instance of SqliteDatabase . The class implements my queries, open, close, etc. (the class is NOT a singleton).
I have an activity, a service and an appwidget in my app.
Where I need the database, I create an object of my class, open , do stuff and close at the end.
for example in the activity I open the db in onStart and close it onStop.
Everything works great except in the appwidget.
If I need to select data in the appwidget onUpdate, then it's ok.
but when I try to do an UPDATE from the appwidget, I get the "database DATABASE_FLE already closeed" error.
What can it be?
I added some logs where I'm closing the db, and non of those lines execute before this error.. the db should be ok.
Any ideas?
Thanks.

What i am thinking about, is case in which android may close/unload your activity (this may happend for example if there is a little memory left on the device), but in this time your appwidget is still active.
Now, because of your activity is closed, hence you db is closed.
Appwidget tryes to update DB but its is already closed.
Check this scenario but anyway you should take this scenario in consideration. :)

The problem was that I compiled an SQLiteStatment object and saved it for future uses, while my database object got replaced..
so SQLiteStatement needs to re-compile again.
I had something like this:
public void func(SQLiteDatabase db) {
if (mStatement == null)
mStatement = db.compileStatement(SQL);
mStatement.execute();
The problem with this is that the db object changed in the function call, and the first db object that compiled statement was already closed.
The solution was to remove the if-null, and to compile the statement for every db object.

Related

Is closing a database opened with window.openDatabase necessary?

The code at the moment reads something in the order of...
DoAnything() {
OpenTheDatabase()
// ... Do all the things! ...
}
However, the database object is never closed. This is worrisome.
The database is opened as follows:
var db = window.openDatabase( ... paramters ... );
No .closeDatabase function exists, or the documentation is incomplete. I thought the following might suffice:
db=null;
I see that sqlite3_close(sqlite3*) and int sqlite3_close_v2(sqlite3*) exist, but I'm unsure how to apply them in this case.
How do I close the database, and is it necessary?
Generally you only have one database connection that you open on app startup, and there is no need to close it while the app is open. It's a single threaded, single user app, so a lot of the normal rules about database connections don't apply.
When the app shuts down, you can rely on the browser to close everything - given the average quality of code on the web, browsers have to be pretty good at cleanup.
Setting db to null and letting the garbage collector do its thing will probably also work, but it is better not to create the extra objects in the first place.

How to over come database not opened exception?

I am implementing an app related to database.
So many times I am calling open and close database connection to insert, update and delete.
It is working fine.
But some times I am getting a database not opened exception in different situations.
How to solve these issues?
Well unless you put proper exception handling you would never know what causes this.
However a good idea is to adopt good ORM mapper for SQL Light with Android and this will improve your database interactions and exception handling and opening and closing it efficiently.
You can opt for SUGAR or ORMLight if you wish; In my opinion this should help you to fix your problem.
Based on the information you provided I can assume that the problem is in your business logic and nobody but you should be able to tell you the root cause.
Without your code here, we won't be able to point you to exact place.
One of the possible reasons can be that by your business logic you are trying to do some operation (insert, update whatever) on closed database.
You can do some workaround to try to ensure that your DB is always open when it is needed. If you implement database getter method with so called lazy initialization approach it will guarantee at least, that the DB is open when you need to access it.
Here is what I am talking about:
1. make a public method which supposed to return DB object:
public SQLiteDatabase getDB() {
if ((mDataBase == null) || (!mDataBase.isOpen())) {
// create or open your database using an OpenHelper
mDataBase = SQLiteOpenHelper.getWritableDatabase();
}
return mDataBase;
}
Now, everywhere in your code use this method to access the DB instead of directly accessing a variable mDataBase.
Note that the code is just to give you an idea and not actually compilable.
Still, I would recommend you to fix your business logic instead of using this workaround.

How to use the same database and cursor through the whole app properly?

I have huge databases (~ 40K rows) which I deal with in my app. There is one activity which has a list view that uses a CursorAdaptor to display and search in the whole database rows. Each time the user deals with a database, I open the database and create the required Cursor and I call Cursor.getCount() in another thread to tackle the laziness issue of cursors and make it fully ready for future operations. It takes around 7 seconds to have Cursor.getCount() done for the huge databases.
Users may invoke this activity multiple times so I store the cursor in a global class as a static data member and I always reuse the same cursor.
I guess that if I did not close the cursor and the database properly I may get weird results. Right?!
My question is: When I should close the cursor and the database?
It will not be possible to close the database and the cursor in Activity.onStop() since I will have to re-open the database and the cursor each time the activity goes from being invisible to visible. And if I did the close in Activity.onDestroy, then the app might be killed by the OS (when device's available memory is low) before the onDestroy is called.
Why don't you turn this global static class into a singleton so that you don't run into instantiation problems, which it sounds like you are referencing. Once you call getInstance() in your singleton you will always get the same cursor and DB connection within that class.

Usage of SQLiteOpenHelper.getWritableDatabase

According to http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#getWritableDatabase%28%29
Once opened successfully, the database is cached, so you can call this
method every time you need to write to the database.
Consider the following snippet:
SQLiteDatabase db1 = openHelperImplObj.getWritableDatabase();
// do something with db1
SQLiteDatabase db2 = openHelperImplObj.getWritableDatabase();
// do something with db2
db2.close();
// do something with db1
db1.close();
I presume the second call to getWritableDatabase() will return the same cached DB (the db1), wouldn't the line db2.close() cause any issue to db1 operations that happen afterward? If so, what is the recommended way to avoid such problem since the second call may happen anywhere, i.e. in a different function or even in different class.
When you open a data base by using db openHelperImplObj.getWritableDatabase();
then following thing check
1>If database is not created then it create database and open it for write mode else created first then open.
2>Second and most important what i have observed if data base is already created then it opened it but if its open already it do nothing, That means it occupy the old instance of data
base that open DB already until you close it.Thats why its better practice to close DB once it
use over
Hope you got

Using the same database in successive activities in Android without memory leak

I'll preface this question with the note that I have looked at this similar question, but I'm still encountering issues. Basically, I want to access the same database in two activities in my Android application. However, when I open it in the second activity, I'm getting two series of messages in my LogCat:
First:
"Uncaught exception thrown by finalizer (will be discarded):
Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor#436053b8 on dogs that has not been deactivated or closed
at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)"
(dogs is the name of a table in my database, dog_data)
Second:
"ERROR/Database(1316): Leak found
ERROR/Database(1316): java.lang.IllegalStateException: /data/data/com..../databases/dog_data SQLiteDatabase created and never closed"
As far as I can tell, I am closing my database upon exiting the first activity. Following the style of the notepad tutorial, I have a wrapper class "DbAdapter" around my SQLiteDatabase, and in the onPause() method of the first activity, I call the close method on that Adapter (which calls the close methods on my SQLiteDatabase and my SQLiteOpenHelper).
I think the issue is how I am trying to reopen the database in my second activity:
SQLiteDatabase db = openOrCreateDatabase("dog_data",
SQLiteDatabase.CREATE_IF_NECESSARY, null);
(I choose not to use a wrapper because I only needed to run one query on the database, perhaps this is an issue).
Can someone advise as to where my issue might be? I'll admit (as may be clear from my question) that I don't fully understand the implications of "closing" a database (the documentation for SQLiteDatabase.close() is not particularly specific), which is probably the main reason for my problem.
Thanks.
Just in case someone happens to encounter a similar issue (seems possible but probably unlikely), I recently stumbled onto the solution. In the insert method of my "DbAdapter", I was (stupidly) checking uniqueness via a query for a row with a given value for one of the fields, and seeing whether that query returned any rows. This was creating a cursor that I wasn't closing, which resulted in the "Finalizing cursor" error noted above.
I've received that error before and had to use cursor.close() to correct the issue. I'm not exactly sure why because there are times when I didn't use close() and received no error. Maybe it's a warning that only gets noticed when it is sitting next to a show stopping error?
I will say the proper procedure is open database connection -> create cursor by running db method -> iterate through cursor -> close cursor -> close database connection.

Categories

Resources