使用Xamarin.Contacts.AddressBook加载多个联系人

时间:2014-07-25 18:26:01

标签: android xamarin

我希望通过Xamarin.Contacts.AddressBook加载多个联系人,目前我有类似的内容:

var loookupIDs = /* load 10 saved contact IDs */
var addressBook = new AddressBook(context) { PreferContactAggregation = true };

foreach(var id in loookupIDs)
{
    var contact = addressBook.Load(id);
    names.Add(contact.DisplayName);
}

然而,这非常慢(在Android设备上测试) - 即使只加载10个联系人。有没有办法批量加载,所以它更快?或者是使用特定于平台的API而不是Xamarin包装器的唯一选择。

2 个答案:

答案 0 :(得分:9)

是的,Xamarin.Mobile有点慢。它结合了所有可能的联系人(电话,邮件等)和所有可能的字段,这是Android参考手册不推荐的。

我建议您使用本机方式使用Cursor查询联系人并根据需要对其进行过滤。可悲的是,Xamarin dev混淆了所有常量,所以这不是一项微不足道的任务。

这是完整的例子

    public class PhoneContactInfo
    {
        public string PhoneContactID { get; set; }
        public string ContactName { get; set; }
        public string ContactNumber { get; set; }
    }

    public IEnumerable<PhoneContactInfo> GetAllPhoneContacts(IEnumerable<int> filterIds = null)
    {
        Log.Debug("GetAllPhoneContacts", "Getting all Contacts");
        var arrContacts = new System.Collections.Generic.List<PhoneContactInfo>();
        PhoneContactInfo phoneContactInfo = null;
        var uri = ContactsContract.CommonDataKinds.Phone.ContentUri;

        string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id, 
                                ContactsContract.Contacts.InterfaceConsts.DisplayName,
                                ContactsContract.CommonDataKinds.Phone.Number
                              };

        //String[] strings = filterIds.Select(k => Convert.ToString(k)).ToArray();
        //string whereClause = ContactsContract.Contacts.InterfaceConsts.Id + " = ? ";

        var cursor = MainActivity.ContextHolder.ContentResolver.Query(uri, projection,
                                null,
                                null,
                                null);

        cursor.MoveToFirst();

        while (cursor.IsAfterLast == false)
        {
            int phoneContactID = cursor.GetInt(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.Id));

            if (filterIds.Contains(phoneContactID))                
            {
                String contactNumber = cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.Phone.Number));
                String contactName = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.DisplayName));

                phoneContactInfo = new PhoneContactInfo()
                {
                    PhoneContactID = Convert.ToString(phoneContactID),
                    ContactName = contactName,
                    ContactNumber = contactNumber
                };

                arrContacts.Add(phoneContactInfo);
            }
            cursor.MoveToNext();
        }
        cursor.Close();
        cursor = null;
        Log.Debug("GetAllPhoneContacts", "Got all Contacts");
        return arrContacts;
    }

如果你想添加一些花哨的异步

public Task<IEnumerable<PhoneContactInfo>> GetAllPhoneContactsAsync(IEnumerable<int> filterIds)
{
    return Task.FromResult(GetAllPhoneContacts(filterIds));
}

另请查看评论whereClause。您可以构建像SQL一样的SQL。 where子句使这个查询更快。只需构建一个包含多个&#39; =&#39;和&#39;或&#39;

P.S。 我没有衡量绩效差异,如果有人有不错的统计数据,我将不胜感激

答案 1 :(得分:-1)

看起来您为每个loookupID访问AdressBook,这可能会导致您的速度问题。

尝试: 1)获取所有联系人,或仅获取您可能感兴趣的联系人。(使用Linq) 2)与找到的联系人进一步合作

Xamarin docs的示例: http://blog.xamarin.com/introducing-xamarin-contacts/

var book = new AddressBook (this) {
    PreferContactAggregation = true
};

foreach (Contact c in book.Where (c => c.LastName == "Smith")) {
    print (c.DisplayName);
    foreach (Phone p in c.Phones)
        print ("Phone: " + p.Number);
    foreach (Email e in c.Emails)
        print ("Email: " + e.Address);
}