2011-09-22 109 views
2

目前,我使用此代码,以获得联系人姓名和电话号码:优化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(); 
     } 
    } 

但这是极其缓慢。

有没有办法在只有一个查询检索的姓名和电话?

回答

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"); 
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); 
+0

在该帖子里说,该代码仅用于“这篇文章是API级别4或更低” – zegnus

3

似乎对我而言,所提到的性能问题源于所提出的实现中固有的“n + 1选择”问题。

  1. 打开游标遍历所有联系人(1)
  2. 为每个联系人打开游标遍历的电话号码为该联系人(N)

更快的方法,如果你真正需要所有这些数据,是从联系人和电话号码返回适当的代理和主键,然后执行在内存中执行联接两个查询。

查询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选择”问题相比,预期影响最小。

+0

我见过很多的这个问题可能的解决方案,但是这一次是最好的FAR !!! – Daemun

+0

我如何获得接触的照片与此相伴的一个查询。 –

相关问题