Search code examples
androidasynchronousfragmentandroid-listfragment

Asynchronously updating ListFragment


I've checked other answers regarding the asynchronous updates of ListFragments and have figured out that the most common problem for the notifyDataSetChanged() method not working is, that developers tend to overwrite the initial adapter source, causing the adapter to lose reference and hence not updating the view. I have a ListFragment that I want to update asynchronously. What I've decided to do, is parse the list data in an AsyncTask and finally update the fragment in onPostExecute(). I want the UI to be as fluid as possible, so I want to avoid doing heavy processing on the main thread. I call the AsyncTask after the views are created to avoid null pointers.

public class CategoryFragment extends ListFragment {

ArrayList<Category> categoriesArray = new ArrayList<Category>();
CategoryAdapter adapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_category, container, false);
            adapter = new CategoryAdapter(getActivity(), R.layout.category_list_item, categoriesArray);
            setListAdapter(adapter);
    return rootView;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    new UpdateUITask().execute(categories);
}

...

    // The async task to update the UI.
class UpdateUITask extends AsyncTask<String, String, ArrayList<Category>>{

    @Override
    protected ArrayList<Category> doInBackground(String... input) {

        // Do some data processing, to fill the categoriesArray.
        // categoriesArray.add(...); -- loop
        return categoriesArray;
    }

    @Override
    protected void onPostExecute(ArrayList<Category> result) {
        super.onPostExecute(result);
        adapter.notifyDataSetChanged();
    }
}
}

The refresh method fires, but produces no result. What else am I missing here? Should I pick a completely different approach?


Solution

  • Its looking like your instance of categoriesArray is getting lost. adapter.notifyDataSetChanged(); doesn't work only in case when your refrence of the listArray which you just passed to the adapter has been lost or changed. So, I would reccomend you to please make sure about this.

    Also if you are going to populate your custom array then, use onProgressUpdate() method of the AsyncTask. It will reduce the loading time too. You can do this like this:

    class UpdateUITask extends AsyncTask<String, Category, ArrayList<Category>>
        {
    
            @Override
            protected ArrayList<Category> doInBackground(String... input)
            {
    
                // Do some data processing, to fill the categoriesArray.
                        //  and get the category objects one by one and call  
                        //publishprogress till data is there
                publishProgress(Category);
    
                        // and finallly just return somthing to get in onpostexecute
    
            }
    
            @Override
            protected void onProgressUpdate(Category... values)
            {
                // TODO Auto-generated method stub
                super.onProgressUpdate(values);
                        categoriesArray.add(...);
                        adapter.notifyDataSetChanged();
            }
    
            @Override
            protected void onPostExecute(ArrayList<Category> result)
            {
                super.onPostExecute(result);
                adapter.notifyDataSetChanged();
            }
        }