How to sort Cursor in Android RecycleView Adapter

First, let’s refresh some memories for Android Cursor.

https://developer.android.com/reference/android/database/Cursor

This interface provides random read-write access to the result set returned by a database query.

Basically cursor is a result holder of a database query, typically for listing data in Android RecyclerView. Like querying the contacts database and display in an address book page.

And you might be aware of the contacts are in alphabet order. And that can easily be achieved by using CursorLoader with sortOrder, which is to specify the order before querying the database and get the result cursor.

Now imagine we are implementing a universal contacts app. This app will show your all kinds of contacts in your address book. For example: Google gmail contacts, Facebook contacts, LinkedIn contacts, …etc, and of course your local device’s contacts.

You might query for individual cursor for each kind of contacts and display a cursor in an individual list view. That is totally perfect as long as the user exactly knows what kind of contacts he/she is looking for. But sometimes they don’t, they only know the contact name they are looking for.

Now you have to try MergeCursor,

MergeCursor mergeCursor = new MergeCursor(new Cursor[]{mGoogleCursor, mFacebookCursor, mLinkedInCursor, mPhoneContactCursor});

Yeah! the mergeCursor will be listing all contacts in the list view and you can do a universal search against this list.

But, they are not fully sorted in alphabet order.

Then how can I sort this merged cursor?

The answer is you can’t.

Cursor itself is like a hard drive’s head, it just moves to different positions to seek for certain sectors and blocks, and then access the data. Therefore you cannot ‘sort a cursor’, also the data is like fixed at its disk position, we are not going to sort the data neither.

Now we know we can’t sort the cursor, we can’t sort the data behind the cursor, then how can we implement a sorted universal contacts?

We are not going to sort the cursor nor data,

We are going to sort the view.

The Android RecyclerView determines a list item’s view in

onBindViewHolder(ViewHolder holder, int position)

Typically in most implementations, we move the cursor to this position and and access the data to setup the viewHolder.

mCursor.moveToPosition(position);
holder.bindData(mContext, mCursor);

So the list item’s position(index) is mapping to the same position in the cursor(index).

Here you probably have sensed how we are going to “sort the view”.

We are going to create an array of all contact items, and sort against this array.

ContactItemInCursor[] contactItems

After the sorting, contactItems is in the desired order, which is the contact display name alphabet, and every contactItems[i].position has its original position in the cursor.

Now all we have to do is when onBindViewHolder() asks for setup a contact item view at position i, we know the cursor data for this contact item is at contactItems[i].position , we just move the cursor to the data position, accessing the cursor data and let it setup the viewHolder.

YES! That’s it. Feel free to share any feedback! Thanks.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store