How do I close the Cursor and Database safely?
Asked Answered
C

6

9

I've fetched the records from Database using Cursor. It works perfectly, but, I get errors in Logcat while I'm using this code

public Cursor fetchAll()
{
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(t1, new String[] {"_id",name, date, prior, time, dateformat}, null, null, null, null, prior); 
    return cursor;
}

My logcat is -

12-16 14:49:20.774: E/Database(18611): close() was never explicitly called on database '/data/data/com.android.application/databases/appZ.db' 
12-16 14:49:20.774: E/Database(18611): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1810)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844)
12-16 14:49:20.774: E/Database(18611):  at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540)
12-16 14:49:20.774: E/Database(18611):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:158)
12-16 14:49:20.774: E/Database(18611):  at com.android.todoapplication.DBHelper.fetchAll(DBHelper.java:91)
12-16 14:49:20.774: E/Database(18611):  at com.android.todoapplication.ApplicationActivity.sc_adapter(ApplicationActivity.java:1210)
12-16 14:49:20.774: E/Database(18611):  at com.android.todoapplication.ApplicationActivity.refresh_data(ApplicationActivity.java:1195)
12-16 14:49:20.774: E/Database(18611):  at com.android.todoapplication.ApplicationActivity.onKeyDown(ApplicationActivity.java:1440)
12-16 14:49:20.774: E/Database(18611):  at android.view.KeyEvent.dispatch(KeyEvent.java:1037)
12-16 14:49:20.774: E/Database(18611):  at android.app.Activity.dispatchKeyEvent(Activity.java:2068)
12-16 14:49:20.774: E/Database(18611):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1643)
12-16 14:49:20.774: E/Database(18611):  at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2471)
12-16 14:49:20.774: E/Database(18611):  at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2441)
12-16 14:49:20.774: E/Database(18611):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1735)
12-16 14:49:20.774: E/Database(18611):  at android.os.Handler.dispatchMessage(Handler.java:99)
12-16 14:49:20.774: E/Database(18611):  at android.os.Looper.loop(Looper.java:123)
12-16 14:49:20.774: E/Database(18611):  at android.app.ActivityThread.main(ActivityThread.java:4627)
12-16 14:49:20.774: E/Database(18611):  at java.lang.reflect.Method.invokeNative(Native Method)
12-16 14:49:20.774: E/Database(18611):  at java.lang.reflect.Method.invoke(Method.java:521)
12-16 14:49:20.774: E/Database(18611):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-16 14:49:20.774: E/Database(18611):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-16 14:49:20.774: E/Database(18611):  at dalvik.system.NativeStart.main(Native Method)

I refered something from here. They told that use getReadableDatabase(). I'm using that method also. And, i've also use this method,

public Cursor fetchAll()
{
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(t1, new String[] {"_id",name, date, prior, time, dateformat}, null, null, null, null, prior); 
   if (cursor!=null)
    {
        cursor.close();
    }
   if (db!=null)
    {
        db.close();
    }
    return cursor;
}

This gives an error like

Database wasn't open.

After, also I get theseerrors in my Database.

How do I acquire the safety close for Cursor and Database after fetching the records?

Consistent answered 16/12, 2011 at 9:52 Comment(0)
T
10

EDIT: If you return a cursor that is already closed, you can't use it. Open the database before calling the method, then close the cursor and then the database after calling the method.

You can close the cursor after you're done with it like this:

Cursor cursor = fetchAll();
... // Do your work with the cursor
cursor.close();

Or if you're using the cursor from an activity, and need to requery (when the activity is restarted, stopped...) you can use this:

Cursor cursor = fetchAll();
startManagingCursor(cursor); // Android will take care of the cursor for you
// Do your work with the cursor

To close database (after closing the cursor, or if inside an activity in onDestroy() preferably):

dbhelper.close();
Tittup answered 16/12, 2011 at 10:2 Comment(1)
This solution is working for me. Thanks, @Noureddine :-)Fiesta
A
3

In your class which extends ContentProvider, if you are opening the database connection and setting the helper as an instance variable in onCreate, you can close the database connection in shutdown.

@Override
public boolean onCreate() {
    mOpenHelper = getDBOpenHelper(); 
    return true;
}
@Override
public void shutdown() {
mOpenHelper.close();
    super.shutdown();
}
Artina answered 22/10, 2012 at 4:30 Comment(0)
U
2

Better practice would be- open it in onResume() and close it in onPause().

Unquiet answered 16/12, 2011 at 9:58 Comment(0)
S
1

You can also refer to this answer (suggests where you should close cursors/db objects connections depending on the state of Activity) or this one (suggests how to close SQLiteDatabase object). No need to elaborate when it's already written once. Despite that, below is idea for the coding part.

    if (dbCursor != null && dbCursor.moveToFirst()) {
            try {
                              //do stuff
            }  catch (exceptions) {
                              //catch possible exceptions
            } finally {

                if (dbCursor != null && !dbCursor.isClosed()) {
                    dbCursor.close();
                }
            }
Sacellum answered 16/12, 2011 at 9:55 Comment(2)
This closes the cursor, not the database.Forme
yeah - have you read the last part of the question? To quote: So anyone tell me How do i acquire the safety close for Cursor and Database after fetching the records.Sacellum
C
1

every time when you call this method database will open in read mode you but you didn't close the database that's why getting this error. open just once like from onCreate() method and close in destroy()

while you can close the cursor after fetching the rows and when there is no more need for cursor then close and set to null

Cowman answered 16/12, 2011 at 9:56 Comment(0)
F
0

Try passing SQLiteDatabase as a parameter to your fetchAll method:

MyDatabase db = new MyDatabase(this);

....

Cursor myCursor = db.fetchAll(db.getReadableDatabase());

myCursor.close();
db.close();




    public Cursor fetchAll(SQLiteDatabase db, String listName) {
        String sql = "select ID _id, Name from ListName where Name = ? order by ID";
        Cursor c = db.rawQuery(sql, new String[] { listName });
        c.moveToFirst();

        return c;
    }
Forster answered 4/7, 2016 at 21:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.