2011-09-22 53 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

我如何獲得接觸的照片與此相伴的一個查詢。 –

相關問題