Cursor finalized without prior close()
Asked Answered
R

4

19

I have a listview. I get data from an SQLite database. I get this error:

error

It occurs when I go from line 20 to 21:

occur

I placed cursor.deactivate() and cursor.close() on line 50, with no result. Why I get this error and how to solve it?

Rrhagia answered 3/5, 2012 at 15:19 Comment(3)
duplicate of #3068820Roundly
Unrelated to the answer.. You should call getReadableDatabase() instead of getWriteableDatabase(). No need to get a writeable db object when all you're doing is reading from it.Neighborly
@thinksteep I saw that question but when I tried the solution it didn't work. Thanks for helpingRrhagia
T
25

You have to close the cursor before the database. Put your code in a try / catch block and in a finally block, close the cursor and then close the database:

try {
    db = ...
} catch(Exception ex) { 
    // Log the exception's message or whatever you like
} finally {
    try {
      if( cursor != null && !cursor.isClosed())
        cursor.close();
       if( db.isOpen() )
        db.close();
    } catch(Exception ex) {}
}

Closing sequence matters a lot while doing IO with DB or Content Providers. For more information refer this link

Tremml answered 3/5, 2012 at 15:27 Comment(1)
I have two devices, a HTC Desire and a Samsung Galaxy Nexus. With the Desire I don't get the error. With The Galaxy Nexus I do.Rrhagia
C
11

to find such problems just enable StrictMode for Debug Version like that:

public void onCreate() {
     if (DEVELOPER_MODE) {
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .detectDiskWrites()
                 .detectNetwork()   // or .detectAll() for all detectable problems
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());
     }
     super.onCreate();
 }

more information @ http://developer.android.com/reference/android/os/StrictMode.html

all the best,

Controvert answered 24/4, 2015 at 11:39 Comment(0)
L
4

Always, remember to close the cursor by calling cursor.close() before closing the database. That should fix your problem.

Loftus answered 11/10, 2012 at 13:43 Comment(0)
B
0

let the activity manage the cursor lifecycly by using startManagingCursor(c) and it will be fine.

Beattie answered 3/5, 2012 at 15:27 Comment(10)
Where do I write this? Because in my DatabaseAdapter class (extends SQLiteOpenHelper) he doesn't find "startmanagingcursor()"Rrhagia
its a method of Activity.for example you are getting a cursor from your DBAdapter and setting it to a listview inside an Activity.Inside the activity, call startManagingCursor(c) before giving to setAdapter()..;Beattie
I work with an ArrayAdapter. So I don't return the cursor but an array instead. How do I need to solve it with an arrayadapter?Rrhagia
In the constructor of your ArrayAdapter: Activity a =(Activity)ctx; a.startManagingCursor(c);Beattie
It's an ArrayAdapter there is no cursor.Rrhagia
your question is about cursor lifecycle.Beattie
Yes of course there's a cursor. But the cursor I use is in the DatabaseAdapter class(A class with all methods to get/add/remove data from database). I use an ArrayAdapter to populate my ListView. So I get the data from the database with a cursor and put that into an arraylist wich I return and give to the ArrayAdapter. So no Cursor in the ArrayAdapterRrhagia
I'm in the same position with an ArrayAdapter populating the ListView. If you find a solution, please do share...Taproot
The solution is very simple. If you use the cursor manipulation using an Activity then use its built in Managers like StartManagingCursor() and StopManagingCurosr() methods. But if you have the cursor manipulation outside the activity then the moment you're done with iterating the cursor and extracted all the data that you needed, call the cursor.close() method. As you may know, it is case sensitive so find the exact cases. For example if you declared your Cursor as cursor then you can use cursor.close(). To be safe I also say cursor = null; :)Loftus
Just say your code; so in your case just before db.close() call the cursor.close() that's it. So the code sequence is cursor.close(); cursor = null; db.close();Loftus

© 2022 - 2024 — McMap. All rights reserved.