2012-08-24 26 views
13

Estoy implementando un AutoCompleteTextView y necesito el nombre y el correo electrónico de todos mis contactos. Encontré este fragmento que estoy ejecutando de forma asíncrona, pero es muy lento.Obtener el nombre y el correo electrónico de la lista de contactos es muy lento

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

Realizo una especie de consulta interna y creo que ese es el problema. ¿Hay alguna forma de ajustarlo y hacerlo más rápido?

+0

¿Lograste que funcione? –

+0

El 'if (cur.getCount()> 0)' externo es redundante y puede eliminarse. – mdup

Respuesta

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

pocas notas:

  • uso justo ContactsContract.CommonDataKinds.Email.CONTENT_URI para obtener la información que necesita, consulte ContactsContract.CommonDataKinds.Email de información lo que las columnas se pueden consultar
  • proyección de uso para obtener sólo aquellas columnas que realmente necesita, se ahorra un poco de memoria y aumentar el rendimiento de la consulta
  • obtener índices de columnas una sola vez, justo antes del ciclo while
+0

Funciona perfectamente. Gracias –

+0

Trabaja como un encanto ..:) – ADT

+0

gracias mucho, mejora increíble –

5

No debe consultar directamente la ContactsContract.Contacts

hacer sólo uno consulta en la ContactsContract.CommonDataKinds con el tipo de datos de correo electrónico.

El ContactsContract.CommonDataKinds.Email hereda muchas otras interfaces que puede usar para construir su proyección. (Ver constantes heredado de la documentación)

Por ejemplo:

import android.provider.ContactsContract.CommonDataKinds.Email; 

[...] 

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

para ser utilizado con el

Email.CONTENT_URI 

Puede recuperar una gran cantidad de información (como identificador de usuario, nombre de visualización del usuario ...) directamente desde el tipo de datos de correo electrónico.

EDIT:

simplemente me di cuenta de que está tratando de construir un AutoCompleteTextView.

debe reemplazar el método runQueryOnBackgroundThread y la convertToString de su CursorAdapter y utilizar el Email.CONTENT_FILTER_URI

Realmente fuertemente que sugiero a echar un vistazo a las muestras ApiDemo.

Especialmente el AutoComplete4.java de ejemplo que puede encontrar HERE.

+1

Gracias Timothée, su explicación está muy bien hecha. Lástima que no puedo marcar ambas respuestas como correctas. Creo que la respuesta de biegleux es muy buena (funciona increíblemente bien) para otros usuarios que buscan un fragmento rápido. –

1
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 , } 
Cuestiones relacionadas