how to translate id to label in cursorloader/cursoradapter

47 views Asked by At

I'm generating a contacts list using a CursorLoader and SimpleCursorAdapter. Each row of the list contains three values: Name, Phone, and PhoneType

The PhoneType is an int, but I want to display the label associated with the type i.e. Mobile, Work, Home, etc..

I know I can enumerate the CursorLoader in onLoaderFinished() and translate each of the phonetypes to type-labels, and put the resulting values in an arraylist. But if I do that, I believe I lose the "live-binding" benefit of the cursor and assume I then consume additional system resources for the array.

I have found the phone-type-label here, (in the Summary section), but referencing this column results in an Invalid Column error. I've tried other URIs, but this is the only one I've found so far that returns The contact name with all of its associated phone numbers and types. Based on the link above, I don't don't really understand why this URI returns the contact name, and not the CONTENT_ITEM_TYPE or CONTENT_TYPE.

I have two questions: (1) Is there a way to translate the ID to its corresponding label without having to enumerate the cursor and manually translate to a label? (2) If I have to enumerate, do I have to place the results in an ArrayList, or is there a way to add an unbound "label column" to the cursor?

Here's the relevant code:

import static android.Manifest.permission.READ_CONTACTS;

public class MainActivity extends AppCompatActivity
        implements LoaderManager.LoaderCallbacks<Cursor> {

    private static String[] LOADER_PROJECTION_CONTACTS = new String[] {
            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Phone.NUMBER,
            ContactsContract.CommonDataKinds.Phone.TYPE,
            ContactsContract.CommonDataKinds.Phone._ID};

    private static String[] ADAPTER_PROJECTION_CONTACTS = new String[] {
            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Phone.NUMBER,
            ContactsContract.CommonDataKinds.Phone.TYPE};

    SimpleCursorAdapter adapter;
    int CONTACTS_LOADER = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int perm = ContextCompat.checkSelfPermission(this, READ_CONTACTS);
        if (perm != PackageManager.PERMISSION_GRANTED)
            ActivityCompat.requestPermissions( this, new String[]{READ_CONTACTS}, 1 );
        else {
            adapter = new SimpleCursorAdapter(
                    this,
                    R.layout.contacts_listview_item,
                    null,
                    ADAPTER_PROJECTION_CONTACTS,
                    new int[]{R.id.txt_contact_name, R.id.txt_contact_phone, R.id.txt_contact_type},
                    0);

            ListView listview_contacts = (ListView) findViewById(R.id.list_contacts);
            listview_contacts.setAdapter(adapter);

            getSupportLoaderManager().initLoader(CONTACTS_LOADER, null, this);
        }
    }

    @Override
    public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle)
    {
        return new CursorLoader(
                this,
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                LOADER_PROJECTION_CONTACTS,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " NOT LIKE '#%'",
                null,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + "," +
                ContactsContract.CommonDataKinds.Phone.TYPE);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        adapter.swapCursor(cursor);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        adapter.swapCursor(null);
    }

}
1

There are 1 answers

0
John Ward On

In order to bind a different value to the UI than the value in the raw data, it looks like a custom adapter must be created. I created a CustomAdapter, extending BaseAdapter, then in the getView() method, switch/cased the phoneType value to convert it to phoneType text. Then I set the TextView in the layout accordingly. This turns out to be a pretty simple solution...when you know the answer.