【问题标题】:Getting name and email from contact list is very slow从联系人列表中获取姓名和电子邮件非常慢
【发布时间】:2012-08-24 12:26:48
【问题描述】:

我正在实施 AutoCompleteTextView,我需要所有联系人的姓名和电子邮件。 我发现我正在异步运行这个 sn-p,但它很慢。

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

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

【问题讨论】:

  • 你成功了吗?
  • 外层if (cur.getCount() > 0)是多余的,可以去掉。

标签: android contacts autocompletetextview android-cursor


【解决方案1】:
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 循环之前获取一次列索引

【讨论】:

  • 我怎样才能有效地阅读整个 v-card 这意味着阅读整个地址簿。
【解决方案2】:

你不应该直接查询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
};

一起使用
Email.CONTENT_URI

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

编辑:

我刚刚意识到您正在尝试构建一个 AutoCompleteTextView。

您应该重写 CursorAdapter 的 runQueryOnBackgroundThread 方法和 convertToString 并使用 Email.CONTENT_FILTER_URI

非常强烈建议您看看 ApiDemo 示例

尤其是您可以找到 HEREAutoComplete4.java 示例。

【讨论】:

  • 感谢 Timothée,您的解释做得很好。太糟糕了,我无法将两个答案都标记为正确。我认为 biegleux 的回答对于其他寻求快速 sn-p 的用户来说非常好(效果非常好)。
【解决方案3】:
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));
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 2016-10-25
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    相关资源
    最近更新 更多