2012-06-06 14 views
5

Estoy tratando de obtener contactos del dispositivo Android. He encontrado un gran código de ejemplo hereobtener contacto problema de rendimiento

Sin embargo, cuando se trata de rellenar una ListActivity con ArrayAdapter que está utilizando ese código que está tomando mucho tiempo - casi 4 segundos en Galaxy S2 y mucho más en los dispositivos más antiguos. Necesito mejorar ese rendimiento. Lo que pensé es implementar Cursor que contendrá más de una dimensión Cursor, y usar SimpleCursorAdapter como el adaptador de lista.
veo algunos problemas con este enfoque:

  • No sé cómo conseguir elemento de la posición específica.
  • cada cursor tiene columnas diferentes.

¿Existe una forma mejor/más fácil de hacerlo?

EDIT:

aquí es mi código:

public List<ContactData> readContacts(){ 
    ContentResolver cr = getContentResolver(); 
    List<ContactData> cd = new ArrayList<ContactData>(); 
    Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, 
      null, null, null, ContactsContract.Contacts.DISPLAY_NAME); 

    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)); 
      if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) { 

       // get the phone number 
       Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null, 
             ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", 
             new String[]{id}, null); 
       while (pCur.moveToNext()) { 
        String phone = pCur.getString(
          pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 
        if (!Utils.isEmpty(phone)) { 
         cd.add(new ContactData(id, name, phone)); 
        } 
       } 
       pCur.close(); 


      } 
     } 
    } 
    return cd; 
} 

EDIT 2:

logró solucionarlo cambiándola a una sola consulta:

public List<ContactData> readContacts(){ 
    ContentResolver cr = getContentResolver(); 
    List<ContactData> cd = new ArrayList<ContactData>(); 
       Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
         new String[]{ContactsContract.CommonDataKinds.Phone._ID,ContactsContract.CommonDataKinds.Phone.NUMBER,ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY}, 
         ContactsContract.CommonDataKinds.Phone.NUMBER + " IS NOT NULL", 
             null, 
             ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY); 
       while (pCur.moveToNext()) { 
        String phone = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 
        String id = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID)); 
        String name = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY)); 
         ContactData cd1 = contactDataProvider.get(); 
         cd1.id = id; 
         cd1.name = name; 
         cd1.phone = phone; 
         cd.add(cd1); 
       } 
       pCur.close(); 
    return cd; 
} 
+0

¿Cuál es la lista completa y precisa de datos de un contacto que desea representar en cada una de sus filas 'ListFragment'? – CommonsWare

+0

Agregué el código de muestra, espero que lo explique (identificación, nombre, teléfono) – oshai

Respuesta

4

Puede obtener el nombre y el ID al mismo tiempo, se obtiene el número de teléfono:

String[] PROJECTION=new String[] {Contacts._ID, Contacts.DISPLAY_NAME, Phone.NUMBER}; 
Cursor pCur = cr.query(Phone.CONTENT_URI, PROJECTION, Phone.CONTACT_ID +" = ?", 
             new String[]{id}, null); 

Esto elimina la sub-consulta por fila.

+0

¡funciona, gracias! Lo usé pero también eliminé el filtrado por id para obtener todos los teléfonos de todos los usuarios. – oshai

3

Usando una Cursor es un gran enfoque para este problema. Para obtener información desde una posición específica, puede usar Cursor.moveToPosition(int position). Luego puede acceder a cualquier campo del Cursor, en este caso un String, usando Cursor.getString(int columnIndex).

Eche un vistazo a la documentación Cursor para obtener más detalles.

La mejor parte de este enfoque es que puede implementar un CursorLoader para realizar la recuperación de datos de fondo por usted. También maneja automáticamente la repoblación de su ListView en cambios de datos, cambios de orientación, etc. Consulte this great tutorial para obtener más información.

+1

CursorLoader es definitivamente una gran manera de hacerlo. También tenga en cuenta las consultas de anidado dentro de la otra. Por último, debe asegurarse de seleccionar solo la información que necesita. –

Cuestiones relacionadas