Question

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?

Was it helpful?

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();
        }
    }

OTHER TIPS

use below code for your AsyncTask, but please make sure again you are changing in the original categoryList.

private class UpdateUITask extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        // Do some data processing, to fill the categoriesArray.
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        adapter.notifyDataSetChanged();
    }
}  

and just run this task with passing any argument.

new UpdateUITask().execute();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top