2012-06-06 1 views
5

Sto cercando di ottenere contatti del dispositivo Android. Ho trovato un ottimo esempio di codice hereottenere contatti prestazioni problema

Tuttavia, quando si cerca di compilare un ListActivity con ArrayAdapter che utilizza il codice che sta prendendo un sacco di tempo - quasi 4 secondi sul galaxy s2 e molto altro ancora sui vecchi dispositivi. Ho bisogno di migliorare quella prestazione. Ciò che ho pensato è implementare Cursor che manterrà più di una dimensione Cursor e utilizzare SimpleCursorAdapter come adattatore di elenco.
Vedo qualche problema con questo approccio:

  • non so come ottenere elemento alla posizione specifica.
  • ogni cursore ha colonne differenti.

C'è un modo migliore/più semplice per farlo?

EDIT:

Ecco il mio codice:

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:

sono riusciti a risolvere il problema cambiando ad una sola query:

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

Qual è l'elenco completo e preciso di parti di dati da un contatto che si desidera visualizzare in ciascuna delle righe 'ListFragment'? – CommonsWare

+0

Ho aggiunto un esempio di codice, spero che spieghi (id, nome, telefono) – oshai

risposta

4

È possibile ottenere il nome e l'ID allo stesso tempo, si ottiene il numero di telefono:

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

Questo elimina la fila per-sub-query.

+0

funziona, grazie! L'ho usato ma ho anche rimosso il filtro dall'ID per ottenere tutti i telefoni di tutti gli utenti. – oshai

3

Utilizzando un Cursor è un ottimo approccio per questo problema. Per ottenere informazioni da una posizione specifica, è possibile utilizzare Cursor.moveToPosition(int position). Quindi è possibile accedere a qualsiasi campo di Cursor, in questo caso a String, utilizzando Cursor.getString(int columnIndex).

Dai un'occhiata alla documentazione Cursor per maggiori dettagli.

La parte migliore di questo approccio è che è possibile implementare uno CursorLoader per eseguire il recupero dei dati in background. Inoltre, gestisce automaticamente il ripopolamento del tuo ListView in caso di modifiche ai dati, cambiamenti di orientamento, ecc. Consulta this great tutorial per ulteriori spiegazioni.

+1

CursorLoader è sicuramente un ottimo modo per farlo. Fai anche attenzione alle query di nidificazione l'una dentro l'altra. Infine, devi assicurarti di selezionare solo le informazioni di cui hai bisogno. –