Running a Query with a CursorLoader

A CursorLoader runs an asynchronous query in the background against a ContentProvider, and returns the results to the Activity or FragmentActivity from which it was called. This allows the Activity or FragmentActivity to continue to interact with the user while the query is ongoing.

Define an Activity That Uses CursorLoader

To use a CursorLoader with an Activity or FragmentActivity, use the LoaderCallbacks<Cursor> interface. A CursorLoader invokes callbacks defined in this interface to communicate with the class; this lesson and the next one describe each callback in detail.

For example, this is how you should define a FragmentActivity that uses the support library version of CursorLoader. By extending FragmentActivity, you get support for CursorLoader as well as Fragment:

public class PhotoThumbnailFragment extends FragmentActivity implements
        LoaderManager.LoaderCallbacks<Cursor> {
...
}

Initialize the Query

To initialize a query, call LoaderManager.initLoader(). This initializes the background framework. You can do this after the user has entered data that's used in the query, or, if you don't need any user data, you can do it in onCreate() or onCreateView(). For example:

    // Identifies a particular Loader being used in this component
    private static final int URL_LOADER = 0;
    ...
    /* When the system is ready for the Fragment to appear, this displays
     * the Fragment's View
     */
    public View onCreateView(
            LayoutInflater inflater,
            ViewGroup viewGroup,
            Bundle bundle) {
        ...
        /*
         * Initializes the CursorLoader. The URL_LOADER value is eventually passed
         * to onCreateLoader().
         */
        getLoaderManager().initLoader(URL_LOADER, null, this);
        ...
    }

Note: The method getLoaderManager() is only available in the Fragment class. To get a LoaderManager in a FragmentActivity, call getSupportLoaderManager().

Start the Query

As soon as the background framework is initialized, it calls your implementation of onCreateLoader(). To start the query, return a CursorLoader from this method. You can instantiate an empty CursorLoader and then use its methods to define your query, or you can instantiate the object and define the query at the same time:

/*
* Callback that's invoked when the system has initialized the Loader and
* is ready to start the query. This usually happens when initLoader() is
* called. The loaderID argument contains the ID value passed to the
* initLoader() call.
*/
@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle)
{
    /*
     * Takes action based on the ID of the Loader that's being created
     */
    switch (loaderID) {
        case URL_LOADER:
            // Returns a new CursorLoader
            return new CursorLoader(
                        getActivity(),   // Parent activity context
                        mDataUrl,        // Table to query
                        mProjection,     // Projection to return
                        null,            // No selection clause
                        null,            // No selection arguments
                        null             // Default sort order
        );
        default:
            // An invalid id was passed in
            return null;
    }
}

Once the background framework has the object, it starts the query in the background. When the query is done, the background framework calls onLoadFinished(), which is described in the next lesson.