2014-01-27 28 views
0

我正在努力將所有聯繫人數據歸爲一個。 我需要: *名 *姓 *電話號碼 *版本 等獲取Android中的所有聯繫人數據 - 多個URI

對於我在整個接觸做一個查詢,然後,爲每個聯繫人的ID,我得到的有關數據。

問題是,它需要很多時間,約400秒的接觸時間超過10秒。我不需要向用戶顯示任何東西,我只是在後臺同步聯繫人與我的服務器,所以我沒有任何UI問題... ... - - - - - - - - - - - - - 只是遍歷聯繫人,看看需要更新並將其添加到我的ArrayList, 然後將其發佈到服務器。

public static void getAllContactsFromDevice() { 

     long startTime = System.currentTimeMillis(); 
     Log.d(TAG, "startTime: " + startTime); 

     // Get all contacts by cursor 
     ContentResolver cr = getContext().getContentResolver(); 
     Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, 
       null, null, null); 
     if (cursor.moveToFirst() && cursor.getCount() > 0) { 
      while (cursor.isAfterLast() == false) { 
       // get contact id on the device DB. 
       String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); 

       String contactNumber = null; 
       // Get all phone numbers. 
       Cursor phones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, 
         ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null); 
       // if the user has numbers 
       // get just the first one for now 
       if (phones.moveToNext()) 
        contactNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 
       // close the cursor to prevent leak 
       phones.close(); 

       // if we dont have a phone number, continue to next contact. 
       if (contactNumber == null) { 
        cursor.moveToNext(); 
        continue; 
       } 

       // get first and last name by contact id 
       String[] projection = new String[]{ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME}; 
       String where = ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; 
       String[] whereParameters = new String[]{contactId, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}; 
       Cursor nameCur = cr.query(ContactsContract.Data.CONTENT_URI, projection, where, whereParameters, null); 

       String given = null; 
       String family = null; 
       try { 
        if (nameCur.getCount() > 0) { 
         nameCur.moveToFirst(); 
         given = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)); 
         family = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)); 
         nameCur.close(); 
        } 
        // if there is no name, continue to next contact. 
        else { 
         nameCur.close(); 
         cursor.moveToNext(); 
         continue; 
        } 
       } catch (Exception e) { 
        e.printStackTrace(); 
        nameCur.close(); 
       } 


       if (given == null || given == "null") 
        given = ""; 
       if (family == null || family == "null") 
        family = ""; 

       String[] mProjection = new String[]{ContactsContract.RawContacts.VERSION}; 
       String[] mWhereParameters = new String[]{contactId}; 
       String mWhere = ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ? "; 
       Cursor mCursor = cr.query(ContactsContract.RawContacts.CONTENT_URI, mProjection, mWhere, mWhereParameters, null); 

       int contactVersion = 0; 
       try { 
        if (mCursor.getCount() > 0) { 
         mCursor.moveToFirst(); 
         contactVersion = mCursor.getInt(mCursor.getColumnIndex(ContactsContract.RawContacts.VERSION)); 
         mCursor.close(); 
        } else { 
         mCursor.close(); 
        } 
       } catch (Exception e) { 
        e.printStackTrace(); 
        mCursor.close(); 
       } 
       cursor.moveToNext(); 

      } 

     } 
     cursor.close(); 
     long endTime = System.currentTimeMillis(); 
     Log.d(TAG, "endTime: " + endTime); 
     Log.d(TAG, "total time: " + (endTime - startTime)); 
    } 

總時間:18280毫秒

我看着HERE developer.android.com但沒有發現任何有用的東西。

this answer沒有什麼幫助。

+0

檢查此鏈接http://stackoverflow.com/questions/11991743/fetching-contact-detail-take-a-lot-of-time-in-android – deniz

+0

不,沒有幫助,我用它來檢查哪個聯繫人應該與我的服務器聯繫人同步。我在另一個線程在背景中做... – Shahar

+0

分頁是可能的嗎?先同步一部分聯繫人然後再滾動同步下一步.....它會減少時間 – deniz

回答

0

問題是,您爲每個聯繫人執行幾個查詢:到電話號碼錶,到結構化名稱表等等。您想批量他們全部並執行單個查詢到主要聯繫人列表,單個查詢到電話號碼列表,等等。

對Genymotion與〜400接觸全數據這種方法給出30倍更好的性能(從2.8s到100ms)。下面是我使用的代碼:我使用android-db-commons

private static <TLeft, TRight> Function<Pair<TLeft, TRight>, TLeft> getExtractLeftFunction() { 
    return new Function<Pair<TLeft, TRight>, TLeft>() { 
    @Override 
    public TLeft apply(Pair<TLeft, TRight> input) { 
     return input.first; 
    } 
    }; 
} 

private static <TLeft, TRight> Map<TLeft, TRight> toMap(Iterable<Pair<TLeft, TRight>> pairs) { 
    Map<TLeft, TRight> result = Maps.newHashMap(); 

    for (Pair<TLeft, TRight> pair : pairs) { 
    result.put(pair.first, pair.second); 
    } 

    return result; 
} 

private static class Name { 
    public final String mGivenName; 
    public final String mFamilyName; 

    private Name(String givenName, String familyName) { 
    mGivenName = givenName; 
    mFamilyName = familyName; 
    } 
} 

public void getAllContactsFromDevice() { 

    long startTime = System.currentTimeMillis(); 
    Log.d(TAG, "startTime: " + startTime); 

    // Get all contacts by cursor 
    ContentResolver cr = getContentResolver(); 

    ImmutableList<Long> contactIds = ProviderAction 
     .query(Contacts.CONTENT_URI) 
     .projection(Contacts._ID) 
     .perform(getContentResolver()) 
     .toFluentIterable(SingleRowTransforms.getColumn(Contacts._ID).asLong()) 
     .toImmutableList(); 

    Map<Long, String> phonesMap = toMap(
     ProviderAction.query(Phone.CONTENT_URI) 
      .projection(
       Phone.CONTACT_ID, 
       Phone.NUMBER 
     ) 
      .whereIn(Phone.CONTACT_ID, contactIds) 
      .perform(getContentResolver()) 
      .toFluentIterable(getToPairFunction(
       SingleRowTransforms.getColumn(Phone.CONTACT_ID).asLong(), 
       SingleRowTransforms.getColumn(Phone.NUMBER).asString()) 
     ) 
); 

    Map<Long, String> contactsWithPhones = Maps.filterValues(phonesMap, Predicates.notNull()); 

    Map<Long, Name> contactNamesMap = toMap(ProviderAction 
     .query(Data.CONTENT_URI) 
     .projection(
      StructuredName.CONTACT_ID, 
      StructuredName.FAMILY_NAME, 
      StructuredName.GIVEN_NAME 
    ) 
     .whereIn(StructuredName.CONTACT_ID, contactsWithPhones.keySet()) 
     .perform(getContentResolver()) 
     .toFluentIterable(getToPairFunction(
      SingleRowTransforms.getColumn(Phone.CONTACT_ID).asLong(), 
      new Function<Cursor, Name>() { 

      private Function<Cursor, String> mFamilyNameGetter = SingleRowTransforms.getColumn(StructuredName.FAMILY_NAME).asString(); 
      private Function<Cursor, String> mGivenNameGetter = SingleRowTransforms.getColumn(StructuredName.GIVEN_NAME).asString(); 

      @Override 
      public Name apply(Cursor input) { 
       return new Name(
        mGivenNameGetter.apply(input), 
        mFamilyNameGetter.apply(input) 
      ); 
      } 
      } 
    )) 
); 

    Map<Long, Integer> versions = toMap(ProviderAction.query(RawContacts.CONTENT_URI) 
     .projection(
      StructuredName.CONTACT_ID, 
      RawContacts.VERSION 
    ) 
     .whereIn(StructuredName.CONTACT_ID, contactNamesMap.keySet()) 
     .perform(getContentResolver()) 
     .toFluentIterable(getToPairFunction(
      SingleRowTransforms.getColumn(StructuredName.CONTACT_ID).asLong(), 
      SingleRowTransforms.getColumn(RawContacts.VERSION).asInteger()) 
    ) 
); 

    long endTime = System.currentTimeMillis(); 
    Log.d(TAG, "endTime: " + endTime); 
    Log.d(TAG, "total time: " + (endTime - startTime)); 
} 

(免責聲明:我的合着者)來執行所有的查詢和處理輸出。該庫不支持將查詢結果放入Map(yet!),這正是您想要在這裏執行的操作,所以上面的代碼有點麻煩,但它仍然能夠勝過處理多個遊標IMO。