Chapter 4. Asynchronous I/O with Loader

The concurrency constructs we've encountered so far have been quite general in purpose, but in this chapter we'll take a look at a construct with a more specific focus—Loader.

In this chapter we will cover the following topics:

  • Introducing Loaders
  • Building responsive apps with AsyncTaskLoader
  • Building responsive apps with CursorLoader
  • Combining Loaders
  • Applications of Loaders

Introducing Loaders

As the name suggests, the job of Loader is to load data on behalf of other parts of the application, and to make that data available across activities and fragments within the same process.

Loaders were introduced to the Android platform at API level 11, but are available for backwards compatibility through the support libraries. The examples in this chapter use the support library to target API levels 7 through 19.

Provided we implement our Loaders correctly, we get a number of benefits:

  • The heavy lifting is automatically performed on a background thread, and the results are safely introduced to the main thread on completion.
  • Loaded data can be cached and redelivered on repeat calls for speed and efficiency.
  • The framework gives us control over when a Loader instance is destroyed, and allows Loaders to live outside the Activity lifecycle, making their data available across the application and across Activity restarts.
  • Loaders monitor their underlying datasource, and reload their data in the background when necessary. The framework includes lifecycle callbacks that allow us to properly dispose of any expensive resources held by our Loaders.

When we use Loaders, we will not do so in isolation, because they form part of a small framework. Loaders are managed objects, and are looked after by a LoaderManager, which takes care of coordinating Loader lifecycle events with the Fragment and Activity lifecycles, and makes the Loader instances available to client code throughout an application.

To connect a Loader with a recipient for the data it loads, the framework provides the LoaderCallbacks interface. LoaderCallbacks requires an implementing class to provide three methods:

CursorLoader onCreateLoader(int id, Bundle bundle);
void onLoadFinished(Loader<Cursor> loader, Cursor media);
void onLoaderReset(Loader<Cursor> loader);

The onCreateLoader method allows us to instantiate the particular Loader implementation we want. The onLoaderFinished method provides a way to receive the result of background loading in the main thread. The onLoaderReset method gives us a place to perform any cleanup that is needed when Loader is being discarded.

Loader is an abstract class, and does not itself implement any asynchronous behavior. Although we can extend Loader directly, it is more common to use one of the two provided subclasses, AsyncTaskLoader or CursorLoader, depending on our requirements.

AsyncTaskLoader is a general-purpose Loader, which we can subclass when we want to load just about any kind of data from just about any kind of source, and do so off the main thread.

CursorLoader extends AsyncTaskLoader, specializing it to efficiently source data from a local database and manage the associated database Cursor correctly.

Let's begin by implementing a simple AsyncTaskLoader to load a bitmap in the background from the MediaStore.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.179.204