2012-06-06 8 views
5

Próbuję uzyskać kontakty z urządzenia z Androidem. znalazłem wielką przykładowy kod hereWystąpił problem z wydajnością kontaktów

Jednak gdy próbuje wypełnić ListActivity z ArrayAdapter że używa tego kodu ma to dużo czasu - prawie 4 sekundy na Galaxy S2 i wiele więcej na starszych urządzeniach. Muszę poprawić ten wynik. Pomyślałem, że zaimplementować Cursor, który będzie posiadać więcej niż jeden wymiar Cursor i użyć SimpleCursorAdapter jako adaptera listy.
Widzę kilka problemów z tym podejściem:

  • nie wiem jak zdobyć pozycję w określonej pozycji.
  • każdy kursor ma inne kolumny.

Czy istnieje lepszy/łatwiejszy sposób na zrobienie tego?

EDIT:

tutaj jest mój kod:

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:

udało się go naprawić, zmieniając go tylko do jednej kwerendy:

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

Jaka jest pełna i dokładna lista danych z kontaktu, który chcesz renderować w każdym wierszu 'ListFragment'? – CommonsWare

+0

Dodałem przykładowy kod, mam nadzieję, że to wyjaśni (id, nazwa, telefon). – oshai

Odpowiedz

4

Można uzyskać nazwę i identyfikator w tym samym czasie można dostać numer telefonu:

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

Eliminuje to per-rzędu sub-zapytania.

+0

to działa, dziękuję! Użyłem go, ale usunąłem filtrowanie według identyfikatora, aby uzyskać wszystkie telefony wszystkich użytkowników. – oshai

3

Używanie Cursor to świetne podejście do tego problemu. Aby pobrać informacje z określonej pozycji, możesz użyć Cursor.moveToPosition(int position). Następnie możesz uzyskać dostęp do dowolnego pola Cursor, w tym przypadku String, używając Cursor.getString(int columnIndex).

Zapoznaj się z dokumentacją Cursor, aby uzyskać więcej informacji.

Najlepsza część tego podejścia polega na tym, że można zaimplementować CursorLoader, aby wykonać pobieranie danych w tle. Automatycznie obsługuje również ponowne przeliczanie wartości ListView w przypadku zmian danych, zmian orientacji itp. Aby uzyskać więcej informacji, należy zapoznać się z tematem this great tutorial.

+1

CursorLoader jest świetnym sposobem na zrobienie tego. Uważaj też na pytania o zagnieżdżanie wewnątrz siebie. Na koniec chcesz się upewnić, że wybierasz tylko te informacje, które potrzebujesz. –