Самый быстрый способ запроса контактов с «номерами мобильных телефонов» на Android - PullRequest
7 голосов
/ 20 мая 2011

Мне нужно получить четкий список всех контактов с устройства и их номера телефонов. Но подождите ... Мы знаем, что некоторым контактам может быть назначено несколько номеров, все зависит от того, как каждый из пользователей хранит свои контакты. Вот что я делаю:

    ContentResolver cr = context.getContentResolver();   
    Uri uri = ContactsContract.Contacts.CONTENT_URI;
    String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME };
    String selection =  ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '1'";
    String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
    ArrayList<user> contacts = new ArrayList<user>();

    Cursor users = a.managedQuery(uri, projection, selection, null, sortOrder);

    while (users.moveToNext()) {
        user u = new user();
        u.PhoneId = users.getInt(users.getColumnIndex(ContactsContract.Contacts._ID));
        u.Name = users.getString(users.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

        String homePhone = "", cellPhone = "", workPhone = "", otherPhone = "";
        Cursor contactPhones = cr.query(Phone.CONTENT_URI, null, Phone.CONTACT_ID + " = " + u.PhoneId, null, null);

        while (contactPhones.moveToNext()) {

            String number = contactPhones.getString(contactPhones.getColumnIndex(Phone.NUMBER));
            int type = contactPhones.getInt(contactPhones.getColumnIndex(Phone.TYPE));
            switch (type) {
                case Phone.TYPE_HOME:   homePhone = number; break;
                case Phone.TYPE_MOBILE:  cellPhone = number; break;
                case Phone.TYPE_WORK:   workPhone = number; break;
                case Phone.TYPE_OTHER:  otherPhone = number; break;
                }
        }        
        u.Phone = ((cellPhone!="") ? cellPhone : ((homePhone!="") ? homePhone : ((workPhone!="") ? workPhone : otherPhone)));
    }

    return contacts;

Процесс работает, но для моих 80 контактов это занимает от 1000 до 2000 миллисекунд, и мне нужно работать намного быстрее:)

1 Ответ

1 голос
/ 21 февраля 2012
Cursor contactPhones = cr.query(Phone.CONTENT_URI, null, 
                                Phone.CONTACT_ID + " = " + u.PhoneId, 
                                null, 
                                null);

Это немного неоптимально в том смысле, что вы кодируете поле идентификатора контакта непосредственно в запросе, а не делаете его аргументом. Это означает, что синтаксический анализатор запросов должен пересматривать запрос каждый раз, вместо того, чтобы использовать одну кэшированную копию.

Вместо этого укажите идентификатор в качестве аргумента:

Cursor contactPhones = cr.query(Phone.CONTENT_URI, null, 
                                Phone.CONTACT_ID + " =? ", 
                                new String[] { Integer.toString(u.PhoneId) }, 
                                null);

javadoc для ContentResolver.query() повторяет это руководство:

Используйте маркеры параметров вопросительного знака, такие как «телефон =?» вместо явные значения в параметре выбора, так что запросы, которые отличаются только тем, что значения будут признаны одинаковыми для кеширования цели.

...