Search code examples
androidandroid-fragmentsandroid-listviewandroid-listfragmentandroid-loader

Updating adapter with AsyncTaskLoader in a regular (support) Fragment not updating ListView


I'm having trouble using the AsyncTaskLoader callbacks to update an adapter in a regular Fragment. I'm using the fragment support library, version 19.1.0.

In my onLoadFinished() callback I simply do an mAdapter.addAll(data). I used the debugger to verify that the callback is called and that all of the data is added to the adapter. The problem is that the list view simply won't update.

I've already tried notifyDataSetChanged() and invalidateViews() - no effect.

All examples or tutorials I've seen so far use a ListFragment or ListActivity without a custom layout; I've tried this and it works fine. In particular, I've tried the sample program from Android Design Patterns loader tutorial. Unfortunately, I can't use ListFragment because I'm using the StickyListHeaders library (but even trying this with a regular ListView doesn't work).

I get the same results when modifying the above sample program to use a Fragment instead of ListFragment by removing the ListFragment-specific method calls and inflating a custom view. The relevant code boils down to this:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mAdapter = new AppListAdapter(getActivity());
    getLoaderManager().initLoader(LOADER_ID, null, this);
}

@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View v = inflater.inflate(R.layout.list_layout, container, false);
    ListView listView = (ListView) v.findViewById(android.R.id.list);
    listView.setAdapter(mAdapter);
    return v;
}

@Override
public void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) {
    mAdapter.setData(data);
}

As I said before, the adapter gets updated but the list view simply won't redraw, even if you add in notifyDataSetChanged and call invalidateViews on the listView. I'm finding it hard to figure out what's going wrong here.


Solution

  • Turns out that the problem was initializing the adapter in onActivityCreated, as it's called after onCreateView - so setAdapter was being passed a null value (and it doesn't complain about that). This wasn't a problem in the ListFragment and ListActivity implementations I'd looked at as you can use their setListAdapter method to associate the adapter with the list view, without keeping your own explicit reference to it. A silly mistake :\