Получение имени и электронной почты из списка контактов очень медленно

Я реализую AutoCompleteTextView, и мне нужно имя и E-Mail всех моих контактов. Я нашел этот фрагмент, что я запускаю асинхронно, но он очень медленный.

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();
        }
    }
}

Я выполняю какой-то внутренний запрос, и я думаю, что проблема. Есть ли способ настроить его и сделать его быстрее?

Ответ 1

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();
    }
}

несколько заметок:

  • используйте только ContactsContract.CommonDataKinds.Email.CONTENT_URI, чтобы получить необходимую информацию, см. ContactsContract.CommonDataKinds.Email для информации о том, какие столбцы вы можете запросить
  • используйте проекцию, чтобы получить только те столбцы, которые вам действительно нужны, вы сохраняете некоторую память и увеличиваете производительность запросов
  • индексировать столбцы только один раз, перед циклом while

Ответ 2

Вы не должны напрямую запрашивать ContactsContract.Contacts

Сделайте запрос один на ContactsContract.CommonDataKinds с типом данных электронной почты.

ContactsContract.CommonDataKinds.Email наследует множество других интерфейсов, которые вы можете использовать для построения своей проекции. (см. унаследованные константы из документации)

Например:

import android.provider.ContactsContract.CommonDataKinds.Email;

[...]

public static final String[]  EMAILS_PROJECTION = new String[] {
    Email._ID,
    Email.DISPLAY_NAME_PRIMARY,
    Email.ADDRESS
};

для использования с

Email.CONTENT_URI

Вы можете получить много информации (например, идентификатор пользователя, отображаемое имя пользователя...) непосредственно из вида данных электронной почты.

EDIT:

Я только понял, что вы пытаетесь создать AutoCompleteTextView.

Вы должны переопределить метод runQueryOnBackgroundThread и convertToString вашего CursorAdapter и использовать Email.CONTENT_FILTER_URI

Я действительно сильно предлагаю вам взглянуть на образцы ApiDemo.

В частности, пример AutoComplete4.java, который вы можете найти ЗДЕСЬ.

Ответ 3

ContentResolver cr = mContext.getContentResolver(); Cursor cursor= mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, PROJECTION, "HAS_PHONE_NUMBER <> 0", null, null); if (cursor!= null) { final int displayNameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); final int numberIndex = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER); final int idIndex= cursor.getColumnIndex(ContactsContract.Contacts._ID); String displayName, number = null, idValue; while (cursor.moveToNext()) {
   displayName = cursor.getString(displayNameIndex);
   idValue= cursor.getString(idIndex);
   Cursor phones  = mContext.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, "contact_id = '" + idValue + "'", null, null);
   phones.moveToFirst();
   try {
   number = phones.getString(phones.getColumnIndex("data1"));
   }
   catch (CursorIndexOutOfBoundsException e)
   {`
   }
   phones.close();
   userList.add(new ContactModel(displayName , number , null , }