2012-08-24 9 views
13

Ich implementiere eine AutoCompleteTextView und ich brauche Name und E-Mail von allen meinen Kontakten. Ich habe dieses Snippet gefunden, das asynchron läuft, aber es ist sehr langsam.Der Name und die E-Mail-Adresse aus der Kontaktliste ist sehr langsam

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

Ich mache eine Art innere Abfrage und ich denke, das ist das Problem. Gibt es eine Möglichkeit, es zu tunen und es schneller zu machen?

+0

Haben Sie es geschafft, es funktioniert zu bekommen? –

+0

Das äußere 'if (cur.getCount()> 0)' ist redundant und kann entfernt werden. – mdup

Antwort

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

paar Anmerkungen:

  • Verwendung ContactsContract.CommonDataKinds.Email.CONTENT_URI nur um Informationen, die Sie benötigen, finden Sie ContactsContract.CommonDataKinds.Email für Informationen, welche Spalten Sie
  • Verwendung Projektion abfragen können Sie wirklich nur die Spalten erhalten müssen, Sie sparen etwas Speicher und erhöhen Abfrage Leistung
  • erhalten Spaltenindizes nur einmal, kurz vor dem While-Zyklus
+0

Funktioniert perfekt. Danke –

+0

Arbeit wie ein Charme ..:) – ADT

+0

Danke viel, erstaunliche Verbesserung –

5

Sie sollten nicht direkt abfragen, um die ContactsContract.Contacts

Fabrikat nur eine Abfrage im ContactsContract.CommonDataKinds mit der E-Mail-Daten Art. Die ContactsContract.CommonDataKinds.Email erbt eine Menge anderer Schnittstellen, die Sie zum Erstellen Ihrer Projektion verwenden können. (Siehe geerbt Konstanten aus der Dokumentation)

Zum Beispiel:

import android.provider.ContactsContract.CommonDataKinds.Email; 

[...] 

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

zu den

Email.CONTENT_URI 

verwendet werden Sie eine Vielzahl von Informationen abrufen können (wie Benutzer-ID, Anzeige Benutzername ...) direkt von der Art der E-Mail-Daten.

EDIT:

ich nur realisiert werden Sie versuchen, eine AutoCompleteTextView zu bauen.

Sie sollten die runQueryOnBackgroundThread-Methode und die convertToString Ihrer Cursor außer Kraft setzen und die Email.CONTENT_FILTER_URI

verwende ich wirklich starkSie vorschlagen einen Blick auf die ApiDemo Proben zu nehmen.

Vor allem die AutoComplete4.java Probe, die Sie HERE finden.

+1

Danke Timothée, deine Erklärung ist sehr gut gemacht. Schade, dass ich nicht beide Antworten als richtig markieren kann. Ich denke, dass Biegleux's Antwort sehr gut ist (funktioniert unglaublich gut) für andere Benutzer, die nach einem kurzen Ausschnitt suchen. –

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 , }