Here it says that SimpleCursorAdapter
's API level 1 constructor is deprecated and the use of LoaderManager
and CursorLoader
is recommended.
But delving into the LoaderManager
and CursorLoader
's use I found this example where inside an inner class that extends a ListFragment
(an extension of Fragment itself I suppose) we create a CursorLoader
. Everything seems ok, except for the fact that CursorLoader
takes a Uri
as an argument. So this implies that I need to create a ContentProvider
to get access to my database.
I must confess it looks like an overkill to have to go through all of this just to create a simple ListView
with items coming from a database. Specially if I have no intention of making my database data available to other apps, and the main purpose of a content provider is to do that.
So is it really worth it?
Especially in cases like mine where the content to be fetched is likely going to be small. I'm seriously considering doing it the old way, what do you say?
I wrote a simple CursorLoader that does not need a content provider:
import android.content.Context;
import android.database.Cursor;
import android.support.v4.content.AsyncTaskLoader;
/**
* Used to write apps that run on platforms prior to Android 3.0. When running
* on Android 3.0 or above, this implementation is still used; it does not try
* to switch to the framework's implementation. See the framework SDK
* documentation for a class overview.
*
* This was based on the CursorLoader class
*/
public abstract class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {
private Cursor mCursor;
public SimpleCursorLoader(Context context) {
super(context);
}
/* Runs on a worker thread */
@Override
public abstract Cursor loadInBackground();
/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
if (isReset()) {
// An async query came in while the loader is stopped
if (cursor != null) {
cursor.close();
}
return;
}
Cursor oldCursor = mCursor;
mCursor = cursor;
if (isStarted()) {
super.deliverResult(cursor);
}
if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
oldCursor.close();
}
}
/**
* Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
* will be called on the UI thread. If a previous load has been completed and is still valid
* the result may be passed to the callbacks immediately.
* <p/>
* Must be called from the UI thread
*/
@Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
@Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
}
It only needs the AsyncTaskLoader
class. Either the one in Android 3.0 or higher, or the one that comes with the compatibility package.