Introduction
The concept of Loaders was introduced in Android 3.0 (API Level 11). The characteristics of Loaders can be enumerated as follows:
- Loaders are basically used to provide asynchronous loading of data for an Activity of Fragment on Non-UI thread. While the application should perform any call to a Loader from the main thread, the Loader (or subclasses of Loader) performs their work in a separate thread and delivers its results to the main thread.
- The code implementation should not derive directly from
android.content.Loader
class but specifically from android.content.CursorLoader
class. - The callbacks of the Loader are invoked at different stages during loading of data in an Activity or Fragment. In short, an Activity or a Fragment are required to implement Listeners to use Loaders.
- Loaders internally use
AsyncTask
to perform the data load. There is no performance gain when Loaders are compared to AsyncTask, provided that the AsyncTask are designed and developed properly. - Loader, more specifically,
CursorLoader
queries the Content Resolver in the background thread so that the application's User Interface is not blocked and returns the loaded Cursor to the Activity or Fragment. - CursorLoader implements Loader protocol for querying cursors.
CursorLoader
handles the life cycle of the cursor. When using CursorLoader, the developer should never call close() on the cursor. - Loader persist the data fetched to avoid repetitive fetch operations for simple Activity refresh event like orientation change, keyboard open etc.
- Loader monitor the source of its data and deliver new results when the content changes. It automatically reconnects to the last loader’s cursor when being recreated after a configuration change avoiding the need to re-query their data. In other words,
CursorLoader
auto updates and hence there is no need to requery the cursor. - Loaders, in particular CursorLoader, are expected to retain their data after being stopped. This allows applications to keep their data across the Activity or fragment's onStop() and onStart() methods, so that when users return to an application, they don't have to wait for the data to reload.
- Loaders are available as a part of the compatibility library. So developers can use it in applications that run on android build previous to HoneyComb.
- Developers should use
CursorLoader
instead of Activity.managedQuery
or Activity.startManagingCursor
starting in android 3.0. - There is only one
LoaderManager
per Activity or Fragment. The LoaderManager
manages the life of one or more Loader instances automatically within an Activity or Fragment.
An application that uses Loaders typically includes the following:
- An Activity or Fragment.
- An instance of the
LoaderManager
. - A
CursorLoader
: to load the data backed by a ContentProvider
. Alternatively, developers are free to implement their own subclass of Loader or AsyncTaskLoader
to load other types of data. - An implementation for
LoaderManager.LoaderCallbacks
. It is a callback interface that lets a client interact with the LoaderManager. - A way of displaying the loader's data, such as a
SimpleCursorAdapter
. - A data source, such as a
ContentProvider
, when using a CursorLoader
.
Using cursor loaders with android < 3.0
- The developers need to use the compatibility library: http://developer.android.com/tools/extras/support-library.html
- Follow these instructions on setting it up: http://developer.android.com/sdk/compatibility- library.html#SettingUp
- The activity must extend
FragmentActivity
. You will probably need to import these classes:
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
If you're using SimpleCursorAdapter
, make sure you replace this line:
import android.widget.SimpleCursorAdapter;
with this:
import android.support.v4.widget.SimpleCursorAdapter;
Steps to write code
public class MyActivity implements LoaderManager.LoaderCallbacks<Cursor>
loadermanager.initLoader(1, null, this);
- The activity needs to implement
LoaderManager.LoaderCallbacks
: - Initialize the loader:
- Implement the loader callback methods.
onCreateLoader
: Instantiate and return a new Loader for the given ID. This is where the cursor is created. onLoadFinished
: Called when a previously created loader has finished its load. Here, you can start using the cursor. onLoaderReset
: Called when a previously created loader is being reset, thus making its data unavailable. It is being reset in order to create a new cursor to query different data. This is called when the last Cursor provided to onLoadFinished()
above is about to be closed. We need to make sure we are no longer using it.
The complete code on how to use Loader is as follows:
package tpg.main;
import tpg.database.DatabaseAccessUtility;
import tpg.database.DatabaseHandler;
import android.app.ListActivity;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.widget.SimpleCursorAdapter;
public class MainActivity extends ListActivity implements LoaderCallbacks<Cursor> {
SimpleCursorAdapter mAdapter;
LoaderManager loadermanager;
CursorLoader cursorLoader;
private static String TAG="CursorLoader";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadermanager=getLoaderManager();
String[] uiBindFrom = { DatabaseHandler.UserTable.name};
int[] uiBindTo = {android.R.id.text1};
mAdapter = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_1, null, uiBindFrom, uiBindTo,0);
setListAdapter(mAdapter);
loadermanager.initLoader(1, null, this);
}
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
String[] projection = { DatabaseHandler.UserTable.id, DatabaseHandler.UserTable.name };
cursorLoader = new CursorLoader(this, DatabaseAccessUtility.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
public void onLoadFinished(Loader<Cursor> loader,Cursor cursor) {
if(mAdapter!=null && cursor!=null)
mAdapter.swapCursor(cursor);
else
Log.v(TAG,"OnLoadFinished: mAdapter is null");
}
public void onLoaderReset(Loader<Cursor> arg0) {
if(mAdapter!=null)
mAdapter.swapCursor(null);
else
Log.v(TAG,"OnLoadFinished: mAdapter is null");
}
}
The above code would just display the entries of DatabaseHandler.UserTable.name database table in the Listview.
Help Documents