Android loaders, the way to go? Android loaders, the way to go? android android

Android loaders, the way to go?


In case someone is looking for the loader version of my previous example : here it is :

package com.sof.test.loader;import java.util.ArrayList;import android.app.LoaderManager;import java.util.List;import android.app.ListActivity;import android.content.AsyncTaskLoader;import android.content.Context;import android.content.Loader;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.view.ViewGroup.LayoutParams;import android.widget.ArrayAdapter;import android.widget.TextView;/** The activity. */public class LoaderTestActivity2 extends ListActivity implements        LoaderManager.LoaderCallbacks<List<Person>> {    private DataSourceOrDomainModel dataSourceOrDomainModel = new DataSourceOrDomainModel();    private List<Person> listPerson;    private PersonListAdapter personListAdapter;    private TextView emptyView;    private Loader<List<Person>> personLoader;    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        listPerson = new ArrayList<Person>();        personListAdapter = new PersonListAdapter(listPerson);        setListAdapter(personListAdapter);        personLoader = new PersonLoader(this, dataSourceOrDomainModel, new ProgressHandler() );        setUpEmptyView();        getLoaderManager().initLoader(0, null, this);        personLoader.forceLoad();    }    public void setUpEmptyView() {        emptyView = new TextView(this);        emptyView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,                LayoutParams.WRAP_CONTENT));        emptyView.setVisibility(View.GONE);        ((ViewGroup) getListView().getParent()).addView(emptyView);        getListView().setEmptyView(emptyView);    }    public void publishProgress(int progress) {        emptyView.setText("Loading data :" + String.valueOf(progress) + " %");    }    @Override    public Loader<List<Person>> onCreateLoader(int arg0, Bundle arg1) {        return personLoader;    }    @Override    public void onLoadFinished(Loader<List<Person>> personLoader, List<Person> result) {        listPerson.clear();        listPerson.addAll(result);        personListAdapter.notifyDataSetChanged();    }    @Override    public void onLoaderReset(Loader<List<Person>> arg0) {        listPerson.clear();        personListAdapter.notifyDataSetChanged();    }    /** List item view factory : the adapter. */    private class PersonListAdapter extends ArrayAdapter<Person> {        public PersonListAdapter(List<Person> listPerson) {            super(LoaderTestActivity2.this, 0, listPerson);        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            if (convertView == null) {                convertView = new PersonView(getContext());            }            PersonView personView = (PersonView) convertView;            personView.setPerson((Person) getItem(position));            return personView;        }    }    private class ProgressHandler implements ProgressListener {        @Override        public void personLoaded(final int count, final int total) {            runOnUiThread( new Runnable() {                @Override                public void run() {                    publishProgress(100 * count / total);                                   }            });        }    }} class PersonLoader extends AsyncTaskLoader<List<Person>> {    private DataSourceOrDomainModel dataSourceOrDomainModel;    private ProgressListener progressHandler;    public PersonLoader(Context context, DataSourceOrDomainModel dataSourceOrDomainModel, ProgressListener progressHandler ) {        super(context);        this.dataSourceOrDomainModel = dataSourceOrDomainModel;        this.progressHandler = progressHandler;    }    @Override    public List<Person> loadInBackground() {        return dataSourceOrDomainModel.getListPerson( progressHandler );    }}

It would be more difficult to add support (support librairy) to this example as there is no equivalent of ListAcitivity in the support librairy. I would have either to create a ListFragment or create an FragmentActivity and give it a layout including a list.


One problem your code has which loaders aim to fix is what happens if your activity is restarted (say due to device rotation or config change) while your async task is still in progress? in your case your restarted activity will start a 2nd instance of the task and throw away the results from the first one. When the first one completes you can end up with crashes due to the fact your async task has a reference is what is now a finished activity.

And yes using loaders often makes for more/more complex code, particularly if you can't use one of the provided loaders.