Search code examples
androidcontactsautocompletetextviewandroid-cursor

Getting name and email from contact list is very slow


I'm implementing an AutoCompleteTextView and I need Name and E-Mail of all my contacts. I found this snippet that I'm running asynchronously but it's very slow.

ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

if (cur.getCount() > 0) {               
    while (cur.moveToNext()) {                  
        String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));                   
        String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

        Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{id}, null); 

            while (emailCur.moveToNext()) { 

                String email = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                    autoCompleteAdapter.add(name + " - " + email);
            }

            emailCur.close();
        }
    }
}

I'm performing a sort of inner query and I think that's the problem. Is there a way to tune it and make it faster?


Solution

  • private static final String[] PROJECTION = new String[] {
        ContactsContract.CommonDataKinds.Email.CONTACT_ID,
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Email.DATA
    };
    
    ...
    
    ContentResolver cr = getContentResolver();
    Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, PROJECTION, null, null, null);
    if (cursor != null) {
        try {
            final int contactIdIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.CONTACT_ID);
            final int displayNameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
            final int emailIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
            long contactId;
            String displayName, address;
            while (cursor.moveToNext()) {
                contactId = cursor.getLong(contactIdIndex);
                displayName = cursor.getString(displayNameIndex);
                address = cursor.getString(emailIndex);
                ...
            }
        } finally {
            cursor.close();
        }
    }
    

    few notes:

    • use just ContactsContract.CommonDataKinds.Email.CONTENT_URI to get information you need, see ContactsContract.CommonDataKinds.Email for information what columns you can query
    • use projection to get only those columns you really need, you save some memory and increase query performance
    • get column indexes only once, just before the while cycle