To implement database access in my application I followed Lars Vogel tutorial, but I'm very confused about a couple of things...
1) Every time a call is made to fetchTodo
a new cursor will be created and returned. Leaving the previous cursor for the garbage collector. So, if I don't use startManagingCursor
or even the CursorLoader
for that matter, should I call a .close()
on the cursor when I'm done with it ? Outside of fetchTodo
scope of course, example:
Cursor cursor = mNotesAdapter.fetchTodo();
// do something...
cursor.close();
I'm done with this cursor and new one will be created on the next fetch, should I close it like this then or should I leave it for the garbage collector? Although I think I'm talking about 2 things entirely different... Point being, should I close it like in the example above or not?
2) Cursor
also has a .deactivate()
method and the documentation says it uses less resources (than active cursors). When exactly should I use this? For instance, in my app, I have a ListActivity
which is populated through a SimpleCursorAdapter
(the code initialization for this is only called once). The cursor being used is a class member variable, because I need it outside the method that populates the list. I need it to requery the database when something is deleted from it. But until a record is deleted, which is a user action and may take a while to happen, should I deactivate the cursor in the meantime? Cause it will be active again when I call .requery()
again. Or the SimpleCursorAdapter
is going to stop working because the cursor is not active?
EDIT: I just tested this one and found out that I can't call deactivate()
after setting up the cursor adapter. The list will be empty if the cursor is not active, so it needs to remain active for as long as the ListActivity is displayed. In the end, we should just let StartManagingCursor
handle it then. Or the new CursorLoader
.
3) I know that startManagingCursor
/stopManagingCursor
are deprecated but I'm not targeting Honeycomb (at least for the time being) and I don't want to deal with the new CursorLoader
for now. But in the tutorial above, startManagingCursor
is used everywhere, but stopManagingCursor
is never called once. Why not? Does Android deals with that in it's own way? Any situation I should call stopManagingCursor
?
Edit: Updated answer to reflect updated question 1:
Yes, you should definitely either tell Android to
startManagingCursor()
, useLoaderManager
/CursorLoader
orclose()
it yourself. Not doing so will leak memory, the GC won't help with that as there's native resources behind theCursor
(e.g. file handles to the database).EDIT to other readers: The OP found an answer and posted it in his question. The following still holds:
I've never used
deactivate()
(there's nodeactive()
), maybe someone else can explain this. If you want really painless requery/updates, do check out theLoaderManager
framework -- it's not only for Honeycomb: using the compat library you can useLoaderManager
(andFragments
) down to Android 1.6. Not only is it less code for you to write, but it completely offloads these things to Android, much more so thanstartManagingCursor()
.EDIT2: Some notes on
LoaderManager
There are
LoaderManager
tutorials on developer.android.com but these are quite... complex and hard to understand the first time like most of the tutorials there. I also had to dig a lot, the best all-in-one stop I found so far is http://mobile.tutsplus.com/tutorials/android/android-sdk_loading-data_cursorloader/ (plus all the javadocs and compat lib source you can find) --- the wayLoaderManager
works is very similar to the (now also deprecated, replaced byDialogFragment
) managed dialogs with theironCreateDialog
,onPrepareDialog
methods where you just tell Android to "show dialog #123" and then Android calls your code with that ID; same for loaders: "load loader #123", Android calls ononCreateLoader()
.The only obvious drawback is initially, that
LoaderManager
relies heavily on theContentProvider
framework and some people seem to really dislike that. Sure, it's additional learning and code, but once you have aContentProvider
for your own data (even if only used privately in your app), all the data-to-view bindng is a breeze withCursorLoader
. IMHO, there's little difference between rolling your own "content provider" and actually implementing theContentProvider
-- but this is just my highly controversial opinion :)Once you call
startManagingCursor()
theCursor
is no longer your problem. Android will take care of closing the Cursor when yourActivity
gets destroyed (user navigates away, orientation change, ...). There's no need to match a call tostartManagingCursor()
with a call tostopManagingCursor()
-- you usually don't want to take on the burden of managing aCursor
again once you've gotten rid of it.