Search code examples
androidbaseadaptercustom-adapterandroid-cursorandroid-cursorloader

Using Custom Adapter with CursorLoader


I'm trying to use CursorLoader to fetch data from my ContentProvider off the UI thread. I then use it to populate my list view. I was using SimpleCursorAdapter before and it works all fine. But now I want to have different views for the list view rows depending upon the data.

So I wrote a custom adapter extending the base adapter.

public class CustomAdapter extends BaseAdapter {

    private Context mContext;
    private LayoutInflater mInflater;

    public CustomAdapter(Context context) {
        mContext = context;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return 10;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        Log.d("CustomAdapter", "Check" + i + 1);
        if (view == null) {
            view = mInflater.inflate(R.layout.listview_text_layout, viewGroup, false);
            //if(text) load text view
            //else load image view
        }

        return view;
    }
}

But to get anything to display, the getCount() method should return a value greater than 0.

How can I get the number of items loaded by the CursorLoader so that all elements be displayed? Currently, I'm just returning 10 to make it work but that's obviously not the right way to do it.

Here's my Fragment class which implements CursorLoader:

public class MessageFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {

    private AbsListView mListView;
    private CustomAdapter mAdapter;
    ...

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_message, container, false);

        getLoaderManager().initLoader(MESSAGES_LOADER, null, this);

        // Set the adapter
        mListView = (AbsListView) view.findViewById(android.R.id.list);
        mListView.setAdapter(mAdapter);

        return view;
    }


    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        String[] projection = {MessageEntry._ID, MessageEntry.MESSAGE_DATA, MessageEntry.MESSAGE_TIMESTAMP};

        switch (i) {
            case MESSAGES_LOADER:
                return new CursorLoader(
                        getActivity(),
                        Uri.parse("content://com.rubberduck.dummy.provider/messages"),
                        projection,
                        null,
                        null,
                        null
                );
            default:
                return null;
        }
    }
}

Also, in my getView() method, I need to access the data so that I can select which layout to inflate. I know we can pass a List of the data to the Custom Adapter, but how do we do it when the data is actually loaded by CursorLoader?


Solution

  • Instead of extending BaseAdapter, you could extend CursorAdapter.

    When onLoadFinished is called you only need to call swapCursor. You don't need to override getCount(). The super already takes care of returning the correct value.