2

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?

yadav_vi
  • 1,289
  • 4
  • 16
  • 46
akshayt23
  • 2,793
  • 3
  • 21
  • 29

2 Answers2

0

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.

yadav_vi
  • 1,289
  • 4
  • 16
  • 46
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
  • A class which extends CursorAdapter expects a Cursor object while instantiation. Where should I instantiate my CustomCursorAdapter class then? Should I do it in the onLoadFinished() function? – akshayt23 May 04 '15 at 20:47
  • instantiate the adapter `onCreateView` like you are doing it now, passing `null` for the cursor. Store the reference in a class member. When onLoadFinished is called, call `mAdapter.swapCursor(cursor)` – Blackbelt May 04 '15 at 20:53
0

SimpleCursorAdapter with ViewBinder set or CursorAdapter is enough to meet your requirements from what I see, you do not need to extend BaseAdapter.

Once you initialize the loader via LoaderManager, you will get the results via onLoadFinished() method.

To refresh the data call swapCursor() method on the adapter

Please note also that the Activity starts all registered loaders in onStart() so the alternative place to launch your loader would be in onActivityCreated().

This tutorial describes the way which @Blackbelt and I are describing:

http://code.tutsplus.com/tutorials/android-fundamentals-properly-loading-data--mobile-5673

Once you dive deeper into loaders I suggest reading the article:

http://chalup.github.io/blog/2014/06/12/android-loaders/

dawid gdanski
  • 2,432
  • 3
  • 21
  • 29