A simple android loader example

Loaders was available since Android 3.0. It is for asynchronously loading data in an activity or fragment. Let’s build a very simple android app using loaders. This app will load a search result returned from iTune’s rest api and display it in a TextView.

1. Make sure you have enabled the INTERNET permission in the manifest xml file since we will be performing network task in the AsyncTaskLoader.

<uses-permission android:name="android.permission.INTERNET"/>

2. The layout xml file for the MainActivity, activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv_json_result"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Loading..."/>
    </ScrollView>
</LinearLayout>

3. The MainActivity.java and that’s it, the loader sample app is completed. This work sequence of this class a nutshell: initLoader -> onCreateLoader -> loadInBackground -> deliverResult -> onLoadFinished

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String> {

    private TextView tvJsonResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvJsonResult = (TextView) findViewById(R.id.tv_json_result);
        getSupportLoaderManager().initLoader(0, null, (LoaderManager.LoaderCallbacks<String>)this).forceLoad();
    }

    @Override
    public Loader<String> onCreateLoader(int id, Bundle args) {
        return new FetchData(this);
    }

    @Override
    public void onLoadFinished(Loader<String> loader, String data) {
        tvJsonResult.setText(data);
    }

    @Override
    public void onLoaderReset(Loader<String> loader) {
    }

    private static class FetchData extends AsyncTaskLoader<String> {

        public FetchData(Context context) {
            super(context);
        }

        @Override
        public String loadInBackground() {
            HttpURLConnection urlConnection = null;
            BufferedReader reader = null;
            String jsonStr = null;
            String line;
            try {
                URL url = new URL("https://itunes.apple.com/search?term=classic");
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestMethod("GET");
                urlConnection.connect();

                // Read the input stream into a String
                InputStream inputStream = urlConnection.getInputStream();
                StringBuffer buffer = new StringBuffer();
                if (inputStream == null) return null;

                reader = new BufferedReader(new InputStreamReader(inputStream));
                while ((line = reader.readLine()) != null) buffer.append(line);

                if (buffer.length() == 0) return null;
                jsonStr = buffer.toString();

            } catch (IOException e) {
                Log.e("MainActivity", "Error ", e);
                return null;
            } finally {
                if (urlConnection != null) urlConnection.disconnect();
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (final IOException e) {
                        Log.e("MainActivity", "Error closing stream", e);
                    }
                }
            }

            return jsonStr;
        }

        @Override
        public void deliverResult(String data) {
            super.deliverResult(data);
        }
    }

}

Some explaination
The main class implements LoaderManager.LoaderCallbacks <String>, where the String indicates the data returned by the loader will be a string, you are free to change it to other data types such as your own custom object, as long as you make sure your callback methods are also defined with the same data type for return type or method arguments.

These are required methods when implementing the interface LoaderManager.LoaderCallbacks. The method names are self explainatory as to what they do. In the onCreateLoader, it initializes the AsyncTaskLoader FetchData to load the data from iTune’s rest service. The data is loaded, it is delivered to the onLoadFinished method.

@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
    return new FetchData(this);
}

@Override
public void onLoadFinished(Loader<String> loader, String data) {
    tvJsonResult.setText(data);
}

@Override
public void onLoaderReset(Loader<String> loader) {
}

The AsyncTaskLoader FetchData is an inner class of the MainActivity class. The method loadInBackground() method does the heavy lifing of getting the data from the network and the method deliverResult() as the name suggests, it delivers the data returned from loadInBackground()

Complete example in Github

Search within Codexpedia

Custom Search

Search the entire web

Custom Search