从联系人列表中获取姓名和电子邮件非常缓慢

Mar*_*zzi 15 android cursor contacts autocompletetextview

我正在实现一个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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在执行一种内部查询,我认为这是问题所在.有没有办法调整它并使其更快?

bie*_*eux 53

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

几点说明:

  • ContactsContract.CommonDataKinds.Email.CONTENT_URI用于获取所需信息,请参阅ContactsContract.CommonDataKinds.Email以获取可查询的列的信息
  • 使用projection只获取你真正需要的那些列,节省一些内存并提高查询性能
  • 在while循环之前只获取一次列索引


Tim*_*nin 6

您不应直接查询ContactsContract.Contacts

请只是一个对查询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
};
Run Code Online (Sandbox Code Playgroud)

与...一起使用

Email.CONTENT_URI
Run Code Online (Sandbox Code Playgroud)

您可以直接从电子邮件数据类型中检索大量信息(例如用户ID,用户显示名称...).

编辑:

我刚刚意识到你正在尝试构建一个AutoCompleteTextView.

您应该覆盖CursorAdapter 的runQueryOnBackgroundThread方法和方法,convertToString并使用Email.CONTENT_FILTER_URI

强烈建议你看一下ApiDemo样本.

特别是您可以在这里找到的AutoComplete4.java示例.