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