目前,我正在使用此代码来获取联系人姓名和电话号码:
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();
}
}
但这非常慢。
有没有办法只在一个查询中检索姓名和电话?
答案 0 :(得分:3)
在我看来,所提出的性能问题源于所提出的实现中固有的“n + 1选择”问题。
如果您确实需要所有这些数据,更快的方法是从联系人和电话号码执行两个查询,返回相应的代理和主键,然后在内存中执行连接。
查询1:通过ContactId将所有联系人作为地图
With the myriad of solutions proposed being sure to pull out the _ID field as the ContactId
查询2:获取所有电话号码并将其存储在列表中
Cursor c = MyO2Application.getContext().getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] {
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER },
null,
null,
null
);
while (c.moveToNext()) {
String id = c.getString(0);
String contactId = c.getString(1); // this is the foreign key to the contact primary key
String displayName = c.getString(2);
String number = c.getString(3);
然后,您可以遍历电话号码列表,通过ContactId从地图中查找联系人,并将电话号码与联系人关联。
1000个联系人的执行速度从60秒下降到4秒。通常情况下,需要权衡内存消耗和对GC的影响。
发布时的观察:将id作为int并使用SparseArray可能是值得考虑的方法。然而,与此处讨论的“n + 1选择”问题相比,预计会产生最小的影响。
答案 1 :(得分:0)
您可以通过其他方式here
详细了解如何操作这是一个片段
//query for the people in your address book
Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null,People.NAME + " ASC");
startManagingCursor(cursor);
//bind the name and the number fields
String[] columns = new String[] { People.NAME, People.NUMBER };
int[] to = new int[] { R.id.name_entry, R.id.number_entry };
SimpleContactAdapter mAdapter = new SimpleContactAdapter(this, R.layout.list_entry, cursor, columns, to);
this.setListAdapter(mAdapter);
答案 2 :(得分:0)
我找到了一种方法:
Cursor people = getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] {Phone._ID, Phone.DISPLAY_NAME, Phone.NUMBER}, null, null, Phone.DISPLAY_NAME + " ASC");