Finalizing a Cursor that has not been deactivated or closed non-fatal error
Asked Answered
G

9

33

i'm getting a "Finalizing a Cursor that has not been deactivated or closed" error on this piece of code. The code is used to fill a listview.

Since it's a non-fatal error , there is no crash and all seems to works fine..but i don't like the error.

If i close the cursor at the end of this code..the listview stay's empty. if i close the cursor in onStop , i get the same error.

How do i fix this??

private void updateList() { 
        DBAdapter db = new DBAdapter(this); 
        db.open(); 
            //load all waiting alarm 
            mCursor=db.getTitles("state<2"); 
            setListAdapter(new MyCursorAdapter(this, mCursor)); 
            registerForContextMenu(getListView()); 
            db.close(); 
        } 


error : 


E/Cursor  ( 2318): Finalizing a Cursor that has not been deactivated 
or closed. database = /data/data/xxxxxxxxxxxxxxx.db, table = alerts, 
query = SELECT _id, alert_id, 
E/Cursor  ( 2318): 
android.database.sqlite.DatabaseObjectNotClosedException: Application 
did not close the cursor or database 
object that was opened here 
E/Cursor  ( 2318):      at 
android.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:210) 
E/Cursor  ( 2318):      at 
android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDr­iver.java: 
53) 
E/Cursor  ( 2318):      at 
android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.j­ava: 
1345) 
E/Cursor  ( 2318):      at 
android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java­: 
1229) 
.... 
.... 
Guenther answered 18/6, 2010 at 8:56 Comment(0)
F
26

You should not be getting that message if you close the Cursor in onStop() or onDestroy(). Please try that again. Or, call startManagingCursor() after you get the Cursor from your query, and Android will close the Cursor on its own.

Fruiter answered 18/6, 2010 at 11:41 Comment(5)
Thanks - startManaginCursor(mCursor) - Fixed it.... The error always occured right after start of the activity..so closing in onStop would not even be called before the error. Thanks.Guenther
@arnold: Maybe you are thinking of the wrong Cursor? There is no reason why you would get that message "right after start of the activity", so I am thinking perhaps you were leaking a Cursor from the previous activity or something.Fruiter
use try catch and in finally block write code cursor.close() and cursor.deactivate(); // only if you want to query storage later stage else cursor.close() is enough. (cursor == null) will also solve the problemLegislator
startManagingCursor(Cursor) is deprecated: "Use the new CursorLoader class with LoaderManager instead."Zadazadack
I know this is an old thread, but nobody stated the obvious. He's creating a cursor and then immediately closing the database without closing the cursor. cursor.close() right before db.close() in the example code should solve that issue. That's why it's happening when the activity is created.Gib
B
13

Scott,

I ran into the same problem as you. Before you close your database, i.e. "db.close()," make sure that your cursors are closed first, i.e. "mCursor.close()"

Like so:

private void updateList()
{ 
    DBAdapter db = new DBAdapter(this);
    db.open();

    //load all waiting alarm
    mCursor=db.getTitles("state<2"); 
    setListAdapter(new MyCursorAdapter(this, mCursor)); 
    registerForContextMenu(getListView()); 

    // Let's close the cursor.
    mCursor.close();
    db.close(); 
} 

You mentioned that if you closed your cursor your list view stays empty. I recommend you pass the information over to a class and copy it over (allocate the memory) then close the cursor.

Bridewell answered 8/9, 2010 at 20:10 Comment(1)
what if i am returning cursor to custom cursor adapter, which create views for me, is there any way to close the cursor then?Rosol
P
2

When a query returns a cursor it is actually positioned "before" the first record in the cursor. An adapter will attempt do a 'getItem' at the first element so it will fail as the cursor is not positioned at any.

In my base adapters I do a cursorMoveToPosition on the getViews. This seems to eliminate the need for the movefirst.

Provincialism answered 19/2, 2011 at 4:56 Comment(1)
Just an added thought for @birdman: Your cursors probably worked before especially if you were using while(moveToNext). Since a cursor is returned before the first record the moveToNext works.Provincialism
L
1

Do not use startManagingCursor() since that is no longer the recommended approach. The issue occurs because a cursor / DB connection is still not closed by the time the finalizer gets to this object. You can avoid that by either allowing a loader to manage the cursor or by tracking all cursor / DB / SQLiteOpenHelper connections yourself and cleaning up after them.

Using a Loader is fairly cumbersome and requires a lot of moving parts for it to work in conjunction with say a list view. On the other hand tracking your cursor and database connections is prone to human error. If the number of cursor / DB objects is low, I'd recommend the latter solution. If not, let a loader handle your connections.

Lor answered 30/9, 2012 at 12:47 Comment(0)
S
1

Close the cursor object wherever you are creating it.

When you create a cursor object and done with traversing through a SQLite table then close it after it has been used. This closing of cursor prevents exception in logcat.

You will not get any exception related to finalizing the cursor that left opened.

This fixed same issue in my Application.

Starter answered 28/12, 2012 at 7:1 Comment(0)
S
0

I struggled with this problem for two days. I was trying to get sample code working which passed a cursor, returned from a database query, directly to List Adapter - no interim adapter. It refused to work - just displayed a blank screen - until I invoked 'moveToFirst()' on the cursor before passing it to the ListAdapter. Go figure! When I comment this out, it breaks.

Just thought that I'd share this to save people the same struggles that I had.

If anyone can shed some light on why this is so, I'd appreciate it. I haven't had to invoke moveToFirst on cursors up to now, to get them to perform properly.

Sectary answered 11/12, 2010 at 12:44 Comment(1)
you should use startManagingCursor otherwise you have to take care of cursor i.e closing, moving etcLegislator
S
0

Just had the same problem and thought to let you know - just in case....

I accidentally called my fetch routine two times and hereby "lost" the resulting cursor of the first call. This caused the error.

Swainson answered 2/11, 2011 at 10:50 Comment(0)
F
0

I too have been having issues with the closing the cursor:

  • Closing the cursor right after setting the list view's adapter causes the cursor to close before the data gets displayed.

  • Can't use startManagingCursor to manage the cursor because it has been deprecated.

  • The new cursorLoader replacement for startManagingCursor seems to be overkill.

  • Moving the cursor's position as suggested did not work.

  • Making the task an inner class of the activity and closing the cursor in the activity's onDestroy method works sometimes but not all the time.

  • Making the task an inner class of the activity and closing the cursor in the activity's onStop method seems to be working.

I also found out that I can close the database and the sqlite open helper before closing the cursor. I can even close them right after setting the list view's adapter. The data will still display.

Forint answered 1/12, 2011 at 2:5 Comment(1)
cursorLoader is an overkill, why do they dump more work on you and less on themDire
H
0

startManagingCursor(cursor);

This has fixed my problem

Heriberto answered 1/2, 2012 at 20:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.