Android loaders: We meet at last

William J. Francis gives you a tutorial on Android loaders that covers just what you need to know to make things work.

A number of colleagues have been singing the praises of Android loaders since they were added in Honeycomb. I've pushed off learning loaders, in part because I'm pretty comfortable with the main construct they replace: the AsyncTask.

The other reason I think I shied away from loaders is because the amount of documentation is overwhelming. Google offers a partial example in its official documentation on loaders (the entire example can be downloaded from its SDK). Plus, there's a very thorough explanation and example on the Android Design Patterns blog. A tutorial that must be divided into four parts is a pretty big commitment for most Android coders who are already busy coding.

One nice thing about contributing to TechRepublic is now and then I get to dive into things I'd ordinarily not have a reason to or make the time for; this is especially true if it's a topic that interests readers. After scouring the web and reading lots about loaders, I've decided to write a different kind of tutorial on the subject. Instead of being an everything-you-ever-wanted-to-know about loaders guide, I like to think I've pulled off a just-what-you-have-to-know-to-make-the-things-work tutorial.

What's a loader, and why would I use it?

Loaders aren't trivial, so why use them in the first place? Well, in most cases, you would use them in the same scenarios where you've been using AsyncTasks; in fact, some loader subclasses extend AsyncTask. Just as AsyncTasks are used to perform any long-running operation that would tie up the user thread and ultimately throw the dreaded Application Not Responding (ANR), loaders perform in the same manner with the same purpose. The main difference is loaders are specialized for loading data. As such, loaders offer a number of efficiency and convenience benefits.

The tutorial

Follow along with the step-by-step tutorial, or, download and import the entire project directly into Eclipse.

1. Create a new Android project in Eclipse. Target Android 3.0 or higher (you can use loaders all the way back to Gingerbread if you include the compatibility library.)

2. In the /res/layout folder, create you activity_main.xml file. To keep things simple, I've implemented a default list view within a linear layout.

<LinearLayout xmlns:android=""
    android:orientation="vertical" >

        android:text="Hello Loaders!" />
    	android:layout_height="wrap_content" /> 


3. We'll create our file in the /src directory. Let's begin by extending a standard Android Activity and implementing the LoaderCallbacks interface. The static int will eventually get used to identify our loader.
package com.authorwjf.loaderexample;

import java.util.ArrayList;
import java.util.List;

import android.content.AsyncTaskLoader;
import android.content.Context;
import android.content.Loader;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity implements LoaderCallbacks<List<String>>{

	private static final int THE_LOADER = 0x01;

4. Let's implement the required callbacks. The onCreateLoader is responsible for building a loader, but the cool thing is, the SDK takes care of hanging onto it. So the first time the method is called with our 0x01 constant, a new loader is created. After that, the same instance is returned. The onFinished callback returns with our data results, and the onLoaderReset is responsible for wiping out the data.

public Loader<List<String>> onCreateLoader(int id, Bundle args) {
	SampleLoader loader = new SampleLoader(this);
	return loader;

public void onLoadFinished(Loader<List<String>> loader, List<String> list) {
	final ListView listview = (ListView) findViewById(;		
	final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
		android.R.layout.simple_list_item_1, list);
public void onLoaderReset(Loader<List<String>> loader) {		
	final ListView listview = (ListView) findViewById(;

5. Our onCreate function must initialize and kick off the loader via the LoaderManager.

protected void onCreate(Bundle savedInstanceState) {		
	getLoaderManager().initLoader(THE_LOADER, null, this).forceLoad();

6. We are going to implement an inner static class that extends AsyncTaskLoader. The loadInBackground override is provided for you to load your actual data. For simplicity's sake, I'm just iterating through a hardcoded array of strings and introducing an artificial delay.

private static class SampleLoader extends AsyncTaskLoader<List<String>> {

public SampleLoader(Context context) {			

public List<String> loadInBackground() {
	final String[] animals = new String[] { "Ape", "Bird", "Cat", "Dog", "Elephant","Fox",
		"Gorilla", "Hyena", "Inch Worm", "Jackalope", "King Salmon","Lizard",
		"Monkey", "Narwhal", "Octopus", "Pig", "Quail", "Rattle Snake", "Salamander",
		"Tiger", "Urchin", "Vampire Bat", "Wombat", "X-Ray Tetra", "Yak", "Zebra"};
	final ArrayList<String> list = new ArrayList<String>();		  
	for (int i = 0; i < animals.length; ++i) {
	      try {				
			Thread.sleep(100); //simulated network delay
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
	return list;

7. Build and load the APK to a device or emulator and give it a whirl.


Final thoughts

If you ran the example, you probably said something to yourself along the lines of, "Gee, that behaves pretty much like it would have using an AsyncTask or even a Handler." You're right. But I think you'll also agree that there isn't much more complexity than those other solutions either. 

Because this sample is so stripped down, it's really little more than a replacement for what you were probably using AsyncTask for. If you feel comfortable with it, start exploring some of the more advanced examples of loaders on the web, and you'll begin to see benefits that far surpass what you get out of the box with AsyncTasks and Handlers. The CursorLoader subclass might be a good next step, especially if you're doing a lot of work with SQLite.

By William J. Francis

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...