2012-08-24 7 views
13

私はAutoCompleteTextViewを実装しており、すべての連絡先の名前と電子メールが必要です。 私は非同期で実行しているこのスニペットを見つけましたが、それは非常に遅いです。連絡先リストからの名前と電子メールの取得が非常に遅い

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

私は一種の内部クエリを実行していますが、それは問題だと思います。それを調整してより速くする方法はありますか?あなたが直接ContactsContract.Contacts

を問い合わせるべきではありません

+0

あなたはそれを動作させることができましたか? –

+0

外側の 'if(cur.getCount()> 0)'は冗長であり、削除することができます。 – mdup

答えて

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

いくつかの注意事項:

  • 使用だけContactsContract.CommonDataKinds.Email.CONTENT_URIあなたが保存し、あなたが本当に必要なカラムだけを取得するために
  • 使用投影を照会することができますどのような列についてはContactsContract.CommonDataKinds.Emailを参照してください、あなたが必要な情報を取得するにはメモリを増やしてクエリのパフォーマンスを向上させる
  • while列のインデックスは、whileサイクルの直前に1回だけ取得する
+0

完全に動作します。ありがとう –

+0

魅力のように動作します..:) – ADT

+0

あまりにも多く、驚くべき改善 –

5

は、電子メールデータの種類とContactsContract.CommonDataKinds上だけクエリを作成します。

ContactsContract.CommonDataKinds.Emailは、プロジェクションを構築するために使用できる他の多くのインターフェイスを継承しています。例えば

を(ドキュメントから継承された定数を参照してください):

import android.provider.ContactsContract.CommonDataKinds.Email; 

[...] 

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

Email.CONTENT_URI 

で使用されるあなたは、ユーザID等の(ユーザーの表示名を多くの情報を取得することができます...)を電子メールデータの種類から直接取得します。

編集:私はちょうどあなたがAutoCompleteTextViewを構築しようとしている実現

あなたは、私が本当に強くrunQueryOnBackgroundThread方法と、あなたのCursorAdapterのconvertToStringをオーバーライドして、Email.CONTENT_FILTER_URI

を使用する必要がありますが、ApiDemoサンプルを見てみることをお勧めします。あなたはHEREを見つけることができます

特にAutoComplete4.javaサンプル。

+1

Timothéeありがとう、あなたの説明はとてもうまくいっています。あまりにも悪い私は両方の答えを正しいとマークすることはできません。私は、迅速なスニペットを探している他のユーザーにとって、biegleuxの答えは非常に優れていると思います。 –

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 , } 
関連する問題