Most visited

Recently visited

Added in API level 11

LoaderManager

public abstract class LoaderManager
extends Object

java.lang.Object
   ↳ android.app.LoaderManager


Interface associated with an Activity or Fragment for managing one or more Loader instances associated with it. This helps an application manage longer-running operations in conjunction with the Activity or Fragment lifecycle; the most common use of this is with a CursorLoader, however applications are free to write their own loaders for loading other types of data. While the LoaderManager API was introduced in HONEYCOMB, a version of the API at is also available for use on older platforms through FragmentActivity. See the blog post Fragments For All for more details.

As an example, here is the full implementation of a Fragment that displays a ListView containing the results of a query against the contacts content provider. It uses a CursorLoader to manage the query on the provider.

public static class CursorLoaderListFragment extends ListFragment
        implements OnQueryTextListener, OnCloseListener,
        LoaderManager.LoaderCallbacks<Cursor> {

    // This is the Adapter being used to display the list's data.
    SimpleCursorAdapter mAdapter;

    // The SearchView for doing filtering.
    SearchView mSearchView;

    // If non-null, this is the current filter the user has provided.
    String mCurFilter;

    @Override public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // Give some text to display if there is no data.  In a real
        // application this would come from a resource.
        setEmptyText("No phone numbers");

        // We have a menu item to show in action bar.
        setHasOptionsMenu(true);

        // Create an empty adapter we will use to display the loaded data.
        mAdapter = new SimpleCursorAdapter(getActivity(),
                android.R.layout.simple_list_item_2, null,
                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
                new int[] { android.R.id.text1, android.R.id.text2 }, 0);
        setListAdapter(mAdapter);

        // Start out with a progress indicator.
        setListShown(false);

        // Prepare the loader.  Either re-connect with an existing one,
        // or start a new one.
        getLoaderManager().initLoader(0, null, this);
    }

    public static class MySearchView extends SearchView {
        public MySearchView(Context context) {
            super(context);
        }

        // The normal SearchView doesn't clear its search text when
        // collapsed, so we will do this for it.
        @Override
        public void onActionViewCollapsed() {
            setQuery("", false);
            super.onActionViewCollapsed();
        }
    }

    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Place an action bar item for searching.
        MenuItem item = menu.add("Search");
        item.setIcon(android.R.drawable.ic_menu_search);
        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
                | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
        mSearchView = new MySearchView(getActivity());
        mSearchView.setOnQueryTextListener(this);
        mSearchView.setOnCloseListener(this);
        mSearchView.setIconifiedByDefault(true);
        item.setActionView(mSearchView);
    }

    public boolean onQueryTextChange(String newText) {
        // Called when the action bar search text has changed.  Update
        // the search filter, and restart the loader to do a new query
        // with this filter.
        String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
        // Don't do anything if the filter hasn't actually changed.
        // Prevents restarting the loader when restoring state.
        if (mCurFilter == null && newFilter == null) {
            return true;
        }
        if (mCurFilter != null && mCurFilter.equals(newFilter)) {
            return true;
        }
        mCurFilter = newFilter;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }

    @Override public boolean onQueryTextSubmit(String query) {
        // Don't care about this.
        return true;
    }

    @Override
    public boolean onClose() {
        if (!TextUtils.isEmpty(mSearchView.getQuery())) {
            mSearchView.setQuery(null, true);
        }
        return true;
    }

    @Override public void onListItemClick(ListView l, View v, int position, long id) {
        // Insert desired behavior here.
        Log.i("FragmentComplexList", "Item clicked: " + id);
    }

    // These are the Contacts rows that we will retrieve.
    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
        Contacts._ID,
        Contacts.DISPLAY_NAME,
        Contacts.CONTACT_STATUS,
        Contacts.CONTACT_PRESENCE,
        Contacts.PHOTO_ID,
        Contacts.LOOKUP_KEY,
    };

    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        // This is called when a new Loader needs to be created.  This
        // sample only has one Loader, so we don't care about the ID.
        // First, pick the base URI to use depending on whether we are
        // currently filtering.
        Uri baseUri;
        if (mCurFilter != null) {
            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                    Uri.encode(mCurFilter));
        } else {
            baseUri = Contacts.CONTENT_URI;
        }

        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
                + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                + Contacts.DISPLAY_NAME + " != '' ))";
        return new CursorLoader(getActivity(), baseUri,
                CONTACTS_SUMMARY_PROJECTION, select, null,
                Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
    }

    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data);

        // The list should now be shown.
        if (isResumed()) {
            setListShown(true);
        } else {
            setListShownNoAnimation(true);
        }
    }

    public void onLoaderReset(Loader<Cursor> loader) {
        // 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.
        mAdapter.swapCursor(null);
    }
}

Developer Guides

For more information about using loaders, read the Loaders developer guide.

Summary

Nested classes

interface LoaderManager.LoaderCallbacks<D>

Callback interface for a client to interact with the manager. 

Public constructors

LoaderManager()

Public methods

abstract void destroyLoader(int id)

Stops and removes the loader with the given ID.

abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args)

Print the LoaderManager's state into the given stream.

static void enableDebugLogging(boolean enabled)

Control whether the framework's internal loader manager debugging logs are turned on.

abstract <D> Loader<D> getLoader(int id)

Return the Loader with the given id or null if no matching Loader is found.

abstract <D> Loader<D> initLoader(int id, Bundle args, LoaderCallbacks<D> callback)

Ensures a loader is initialized and active.

abstract <D> Loader<D> restartLoader(int id, Bundle args, LoaderCallbacks<D> callback)

Starts a new or restarts an existing Loader in this manager, registers the callbacks to it, and (if the activity/fragment is currently started) starts loading it.

Inherited methods

From class java.lang.Object

Public constructors

LoaderManager

Added in API level 11
LoaderManager ()

Public methods

destroyLoader

Added in API level 11
void destroyLoader (int id)

Stops and removes the loader with the given ID. If this loader had previously reported data to the client through onLoadFinished(Loader, Object), a call will be made to onLoaderReset(Loader).

Parameters
id int

dump

Added in API level 11
void dump (String prefix, 
                FileDescriptor fd, 
                PrintWriter writer, 
                String[] args)

Print the LoaderManager's state into the given stream.

Parameters
prefix String: Text to print at the front of each line.
fd FileDescriptor: The raw file descriptor that the dump is being sent to.
writer PrintWriter: A PrintWriter to which the dump is to be set.
args String: Additional arguments to the dump request.

enableDebugLogging

Added in API level 11
void enableDebugLogging (boolean enabled)

Control whether the framework's internal loader manager debugging logs are turned on. If enabled, you will see output in logcat as the framework performs loader operations.

Parameters
enabled boolean

getLoader

Added in API level 11
Loader<D> getLoader (int id)

Return the Loader with the given id or null if no matching Loader is found.

Parameters
id int
Returns
Loader<D>

initLoader

Added in API level 11
Loader<D> initLoader (int id, 
                Bundle args, 
                LoaderCallbacks<D> callback)

Ensures a loader is initialized and active. If the loader doesn't already exist, one is created and (if the activity/fragment is currently started) starts the loader. Otherwise the last created loader is re-used.

In either case, the given callback is associated with the loader, and will be called as the loader state changes. If at the point of call the caller is in its started state, and the requested loader already exists and has generated its data, then callback onLoadFinished(Loader, D) will be called immediately (inside of this function), so you must be prepared for this to happen.

Parameters
id int: A unique identifier for this loader. Can be whatever you want. Identifiers are scoped to a particular LoaderManager instance.
args Bundle: Optional arguments to supply to the loader at construction. If a loader already exists (a new one does not need to be created), this parameter will be ignored and the last arguments continue to be used.
callback LoaderCallbacks: Interface the LoaderManager will call to report about changes in the state of the loader. Required.
Returns
Loader<D>

restartLoader

Added in API level 11
Loader<D> restartLoader (int id, 
                Bundle args, 
                LoaderCallbacks<D> callback)

Starts a new or restarts an existing Loader in this manager, registers the callbacks to it, and (if the activity/fragment is currently started) starts loading it. If a loader with the same id has previously been started it will automatically be destroyed when the new loader completes its work. The callback will be delivered before the old loader is destroyed.

Parameters
id int: A unique identifier for this loader. Can be whatever you want. Identifiers are scoped to a particular LoaderManager instance.
args Bundle: Optional arguments to supply to the loader at construction.
callback LoaderCallbacks: Interface the LoaderManager will call to report about changes in the state of the loader. Required.
Returns
Loader<D>

Hooray!