Question

My app has a listView populated by the contacts registered on the device, but when i load the listView, it takes too long! Here is my code:

public List<Contact> getContactsList(Context context, ContentResolver contentResolver) {

    List<Contact> listContatos = new ArrayList<Contact>();
    Uri uri = ContactsContract.Contacts.CONTENT_URI;

    Cursor cursorContacts = contentResolver.query(uri, null, null, null, ContactsContract.Contacts.DISPLAY_NAME + " COLLATE NOCASE ASC;");
    try {
        // while there is a next contact, retrieves your data
        while (cursorContacts.moveToNext()) {

            Contact c = getContact(context, cursorContacts);

            if (c != null) {
                listContatos.add(c);
            }
        }
    } finally {

        // Closes Cursor
        cursorContacts.close();
    }
    return listContatos;
}





public Contact getContact(Context context, Cursor contactsCur) {

    Contact c = new Contact();

    // get contact id
    long id = contactsCur.getLong(contactsCur.getColumnIndexOrThrow(BaseColumns._ID));
    String strId = contactsCur.getString(contactsCur.getColumnIndex(BaseColumns._ID));

    // get contact name
    String name = contactsCur.getString(contactsCur.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));     

    boolean temFone = false;
    // if return is different than 1, doesn't has phone number
    temFone = "1".equals(contactsCur.getString(contactsCur.getColumnIndexOrThrow(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
    if (temFone) {
        contactsCur = context.getContentResolver().query(
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                new String[] { strId }, null);

        ArrayList<PhoneNumber> phones = new ArrayList<PhoneNumber>();
        while (contactsCur.moveToNext()) {

            int idx = contactsCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

            if (idx != -1) {
                String phoneNumber = contactsCur.getString(contactsCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                int phonetype = contactsCur.getInt(contactsCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
                String customLabel = contactsCur.getString(contactsCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.LABEL));
                String phoneLabel = (String) ContactsContract.CommonDataKinds.Phone.getTypeLabel(context.getResources(), phonetype, customLabel);

                phones.add(new PhoneNumber(phoneLabel, phoneNumber));                    
            }
        }
        c.setPhones(phones);

        contactsCur.close();
    } else {
        c.setPhones(null);
    }

    loadAddress(context, c, id);
    c.setContactId(id);
    c.setName(name);
    loadEmails(context, c, id);
    loadPhotoUri(context, c, id);
    return c;
}







private void loadEmails(Context context, Contact c, long id) {

    Cursor cursor = context.getContentResolver().query(
            ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
            ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + id,
            null, null);

    ArrayList<ContactMail> emails = new ArrayList<ContactMail>();
    while (cursor.moveToNext()) {
        int idx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);

        if (idx != -1) {
            String stremail = cursor.getString(idx);

            int emailtype = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
            String customLabel = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.LABEL));
            String emailLabel = (String) ContactsContract.CommonDataKinds.Email.getTypeLabel(context.getResources(), emailtype, customLabel);

            if (!stremail.equals(""))
                emails.add(new ContactMail(stremail, emailLabel));
        }
    }
    c.setEmails(emails);
    cursor.close();

}

private void loadAddress(Context context, Contact c, long id) {

    Cursor cursor = context.getContentResolver().query(
            ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI, null, ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID + " = " + id, null, null);

    ArrayList<Address> addresses = new ArrayList<Address>();
    while (cursor.moveToNext()) {
        int idx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.DATA);

        if (idx != -1) {                
            String address = cursor.getString(idx);

            int addresstype = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.TYPE));
            String customLabel = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.LABEL));
            String addressLabel = (String) ContactsContract.CommonDataKinds.StructuredPostal.getTypeLabel(context.getResources(), addresstype, customLabel);

            if (!address.equals(""))
                addresses.add(new Address(address, addressLabel, null));


        }
    }
    c.setAddresses(addresses);
    cursor.close();
}

public void loadPhotoUri(Context context, Contact c, long id) {

    Cursor cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
                    null,
                    ContactsContract.Data.CONTACT_ID
                            + "="
                            + id
                            + " AND "

                            + ContactsContract.Data.MIMETYPE
                            + "='"
                            + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
                            + "'", null, null);

    while (cursor.moveToNext()) {
        int idx = cursor
                .getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.DATA);

        if (idx != -1) {
            Uri person = ContentUris.withAppendedId(
                    ContactsContract.Contacts.CONTENT_URI, id); 
            c.setPhoto( Uri.withAppendedPath(person,
                    ContactsContract.Contacts.Photo.CONTENT_DIRECTORY));
            }
        } 
    } 

It's working just fine, perfectly, the only problem is that takes forever to get all contacts information's. I use the getContact method to get all detailed info about every contact in the device, than in getContactsList I put then in a list of Contact. The list of Contact is used by the adapter of the listView.

Thanks in advance!

Sorry about any english mistakes...

Was it helpful?

Solution 2

I had the same problem. Had to show all the contacts names and phone numbers - was working great but took too long.

Being new to the Android development world, I did some research about it and found the following post:

which was very useful for me.

I assume the problem is that you are making an inner query so it takes you forever. The main problems with my code was getting column indexes more then once, (so I changed it to be once just before the while cycle), and that not-very-clear inner query that I had inside my code, and found a way to take it out.

Try to use the example in that post and see if it helps (hopefully it will - because for me it was perfect!)

Good luck

OTHER TIPS

After so many Research I found this solution 100% fast loading.

Loading all contact with Cursor Loader

String[] PROJECTION = new String[] {
            ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
            ContactsContract.Contacts.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Phone.NUMBER };
    ArrayList<ContactBean> listContacts = new ArrayList<>();
    CursorLoader cursorLoader = new CursorLoader(context,
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION,
            null, null, "UPPER(" + ContactsContract.Contacts.DISPLAY_NAME
                    + ")ASC");

    Cursor c = cursorLoader.loadInBackground();

    if (c.moveToFirst()) {

        int Number = c
                .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
        int Name = c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);

        do {

            try {
                String phNumber = c.getString(Number);
                String phName = c.getString(Name);




            } catch (Exception e) {

            }

        } while (c.moveToNext());

        c.close();
    }

Here is my fast solution:

Cursor cursorPhones = getContentResolver().query(
    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
    new String[]{
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Phone.NUMBER,
        ContactsContract.CommonDataKinds.Phone.TYPE,
        ContactsContract.CommonDataKinds.Phone.LABEL
    },
    ContactsContract.Contacts.HAS_PHONE_NUMBER + ">0 AND LENGTH(" + ContactsContract.CommonDataKinds.Phone.NUMBER + ")>0",
    null,
    ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
);

while (cursorPhones.moveToNext()) {

    String displayName = cursorPhones.getString(cursorPhones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
    String number = cursorPhones.getString(cursorPhones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
    int type = cursorPhones.getInt(cursorPhones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
    String label = cursorPhones.getString(cursorPhones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.LABEL));
    CharSequence phoneLabel = ContactsContract.CommonDataKinds.Phone.getTypeLabel(context.getResources(), type, label);

}

cursorPhones.close();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top