优化 contentProvider 查询以检索联系人姓名和电话
目前,我正在使用此代码来获取联系人姓名和电话号码:
ContentResolver contentResolver = getContentResolver();
Cursor people = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
int nameIndex = people.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
int idIndex = people.getColumnIndex(ContactsContract.Contacts._ID);
int hasPhoneNumberIndex = people.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
String name, id;
int hasPhoneNumber;
while(people.moveToNext()){
name = people.getString(nameIndex);
id = people.getString(idIndex);
hasPhoneNumber = people.getInt(hasPhoneNumberIndex);
if(hasPhoneNumber > 0){
Cursor phones = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+id, null, null);
phones.moveToFirst();
int phoneIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String phone = phones.getString(phoneIndex);
HashMap<String, String> namePhoneType = new HashMap<String, String>();
namePhoneType.put("Name", name);
namePhoneType.put("Phone", phone);
m_peopleList.add(namePhoneType);
phones.close();
}
}
但这非常慢。
有没有一种方法可以仅在一次查询中检索姓名和电话?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在我看来,所提到的性能问题源于所提出的实现中固有的“n+1 选择”问题。
如果您确实需要所有这些数据,更快的方法是从联系人和电话执行两个查询返回适当的代理键和主键的数字,然后在内存中执行连接。
查询 1:通过 ContactId 将所有联系人获取为地图
查询 2:获取所有电话号码并将它们存储在列表中
然后您可以迭代电话号码列表,通过 ContactId 从地图中查找联系人并将电话号码关联起来与联系。
1000 个联系人的执行速度从 60 秒降至 4 秒。通常情况下,需要在内存消耗和对 GC 的影响之间进行权衡。
发布时的观察:将 ids 作为 int 获取并使用 SparseArray 可能是一种值得考虑的方法。然而,与此处解决的“n+1 选择”问题相比,预计影响很小。
It seems to me that the noted performance issue stems from the inherent "n+1 select" problem in the implementations proposed.
A faster approach, if you truly need all this data, is to perform two queries from contacts and phone numbers returning the appropriate surrogate and primary keys and then performing the join in memory.
Query 1: get all contacts as a Map by ContactId
Query 2: get all the phone numbers and store them in a list
You can then iterate through the list of phone numbers, looking up the contact from the map by ContactId and associate the phone numbers with the contact.
Execution speeds for 1000 contacts went from 60 seconds down to 4 seconds. As is often the case, there is a trade-off on memory consumption and impact to GC.
Observation while posting: getting the ids as an int and using SparseArray may be an approach worth considering. Minimal impact expected, however, compared to the "n+1 select" issue addressed here.
您可以阅读有关如何以不同方式执行此操作的更多信息 这里
这是一个片段
You can read more about how to do it in a different way here
Here's a snippet
我找到了一种方法:
I've founded a way: