Android loaders, the way to go?

后端 未结 2 448
旧时难觅i
旧时难觅i 2021-01-30 18:07

I am used to building lists in android using adapters. If I need some long-to-get data, I use an asynctask, or a simple runnable, to update the data structure on which the adapt

相关标签:
2条回答
  • 2021-01-30 18:16

    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.

    0 讨论(0)
  • 2021-01-30 18:22

    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.

    0 讨论(0)
提交回复
热议问题