I'm trying to get a list of contacts in my device that have phone numbers, using a CursorLoader, like so:
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {
Contacts._ID, Contacts.DISPLAY_NAME }, null, null, Contacts.DISPLAY_NAME);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
This works perfectly sometimes and sometimes does not work. It changes from one app launch to the other. The stacktrace for the exception that I get is posted below. I'm passing the cursor to IndexedNameAdapter
which is an extension of SimpleCursorAdapter
that includes an AlphabetIndexer
for fast scrolling:
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.SimpleCursorAdapter;
import android.widget.AlphabetIndexer;
import android.widget.SectionIndexer;
public class IndexedNameAdapter extends SimpleCursorAdapter implements SectionIndexer {
private AlphabetIndexer mAlphabetIndexer;
private String[] from;
public IndexedNameAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
this(context, layout, c, from, to, 0);
}
public IndexedNameAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
this.from = from;
setAlphabetIndexerCursor(c, from);
}
@Override
public Cursor swapCursor(Cursor c) {
setAlphabetIndexerCursor(c, from);
// error occurs here:
return super.swapCursor(c);
}
private void setAlphabetIndexerCursor(Cursor c, String[] columns) {
if (c != null) {
mAlphabetIndexer = new AlphabetIndexer(c, c.getColumnIndex(columns[0]), "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
mAlphabetIndexer.setCursor(c);
}
}
@Override
public int getPositionForSection(int section) {
return mAlphabetIndexer.getPositionForSection(section);
}
@Override
public int getSectionForPosition(int position) {
return mAlphabetIndexer.getSectionForPosition(position);
}
@Override
public Object[] getSections() {
return mAlphabetIndexer.getSections();
}
}
Here is the error I'm seeing:
java.lang.IllegalArgumentException: column 'display_name' does not exist
at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:303)
at android.database.CursorWrapper.getColumnIndexOrThrow(CursorWrapper.java:78)
at android.support.v4.widget.SimpleCursorAdapter.findColumns(SimpleCursorAdapter.java:317)
at android.support.v4.widget.SimpleCursorAdapter.swapCursor(SimpleCursorAdapter.java:328)
at com.mypackage.myprofile.IndexedNameAdapter.swapCursor(IndexedNameAdapter.java:29)
at com.mypackage.myprofile.ProfileUserFragment.onLoadFinished(ProfileUserFragment.java:52)
at com.mypackage.myprofile.ProfileUserFragment.onLoadFinished(ProfileUserFragment.java:1)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:427)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:395)
at android.support.v4.content.Loader.deliverResult(Loader.java:103)
at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:81)
at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:35)
at android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:221)
at android.support.v4.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:61)
at android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:461)
at android.support.v4.content.ModernAsyncTask.access$500(ModernAsyncTask.java:47)
at android.support.v4.content.ModernAsyncTask$InternalHandler.handleMessage(ModernAsyncTask.java:474)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5039)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
I don't usually like answering my own question but I did eventually find the solution to my problem.
I had another fragment in the same activity that also implemented LoaderCallbacks<Cursor>
, and I did not have a unique id for the two cursors. I was getting a cursor for the wrong loader in this fragment.
I thought that because they were in two different fragments that would never be visible at the same time, I would not need a unique ID but that was incorrect.