Praveenkumar
Praveenkumar

Reputation: 24506

How do I close the Cursor and Database safely?

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?

Upvotes: 9

Views: 20450

Answers (6)

live-love
live-love

Reputation: 52494

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

Upvotes: 0

Nichole
Nichole

Reputation: 31

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

Upvotes: 3

hovanessyan
hovanessyan

Reputation: 31483

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

Upvotes: 1

Noureddine AMRI
Noureddine AMRI

Reputation: 2942

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

Upvotes: 10

Hiral Vadodaria
Hiral Vadodaria

Reputation: 19250

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

Upvotes: 2

Pratik
Pratik

Reputation: 30855

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

Upvotes: 1

Related Questions