3

Мне нужно прочитать контакты с устройства. Поля, которые я требую, - ID, Display Name, Phone Number (Все типы) Email id (Все типы) и «Фотография». Для этого сейчас я так делаю.Как получить всю информацию о контактах от поставщика контента с одним запросом?

1: Во-первых, я читаю все id с от ContactsContract.Contacts.CONTENT_URI;, как показано ниже

 Uri contactsUri = ContactsContract.Contacts.CONTENT_URI; 
     // Querying the table ContactsContract.Contacts to retrieve all the contacts 
     String[] projection = {ID}; 
     Cursor contactsCursor = mContentResolver.query(contactsUri, projection, null, null, 
       "upper(" + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + ") ASC"); 

2: Тогда итерацию через этот курсор, чтобы прочитать поля из милиции всех контактов.

if (contactsCursor.moveToFirst()) { 
      do { 
       long contactId = contactsCursor.getLong(contactsCursor.getColumnIndex(ID)); 
        Uri dataUri = ContactsContract.Data.CONTENT_URI; 
       // Querying the table ContactsContract.Data to retrieve individual items like 
       // home phone, mobile phone, work email etc corresponding to each contact 
        String[] columns = {CONTACT_ID, PHOTO_URI, DISPLAY_NAME, MIME_TYPE, DATA_1, DATA_2, DATA_4}; 
        String selection = ContactsContract.Data.CONTACT_ID + "=" + contactId; 
        Cursor dataCursor = mContentResolver.query(dataUri, columns, 
         selection, 
         null, null); 
           if (dataCursor.moveToFirst()) { 
           // Getting Display Name 
           displayName = dataCursor.getString(dataCursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME)); 
           do { 
            // Getting Phone numbers 
            String mimeType = dataCursor.getString(dataCursor.getColumnIndex(MIME_TYPE)); 
            switch (mimeType) { 
              case ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE: 
              String phoneNumber = dataCursor.getString(dataCursor.getColumnIndex(DATA_1)); 
              switch (dataCursor.getInt(dataCursor.getColumnIndex(DATA_2))) { 
            case ContactsContract.CommonDataKinds.Phone.TYPE_HOME: 
             homePhone = phoneNumber; 
             break; 
            case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE: 
             mobilePhone = phoneNumber; 
             break; 
            case ContactsContract.CommonDataKinds.Phone.TYPE_WORK: 
             workPhone = phoneNumber; 
             break; 
            default: 
             otherPhone = phoneNumber; 
           } 
           break; 
           // Getting emails 
           case ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE: 
           switch (dataCursor.getInt(dataCursor.getColumnIndex(DATA_2))) { 
            case ContactsContract.CommonDataKinds.Email.TYPE_HOME: 
             homeEmail = dataCursor.getString(dataCursor.getColumnIndex(DATA_1)); 
             break; 
            case ContactsContract.CommonDataKinds.Email.TYPE_WORK: 
             workEmail = dataCursor.getString(dataCursor.getColumnIndex(DATA_1)); 
             break; 
            default: 
             otherEmail = dataCursor.getString(dataCursor.getColumnIndex(DATA_1)); 
           } 
           break; 
           // getting photo Uri 
           case ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE: 
           if (dataCursor.getString(dataCursor.getColumnIndex(PHOTO_URI)) != null) { 
            photoUri = Uri.parse(dataCursor.getString(dataCursor.getColumnIndex(PHOTO_URI))); 
           } 
           break; 
         } 

        } while (dataCursor.moveToNext()); 


       } while (contactsCursor.moveToNext()); 

Запросы работают нормально, но проблема заключается в том, что требуется слишком много времени для повторения и получения информации о каждом контакте. Первый запрос возвращается быстро, но вся задержка теперь находится во второй части, то есть итерации по каждой строке первого запроса и запроса для каждого поля. Можно ли это сделать в одном запросе соединения, чтобы я мог оптимизировать производительность?

+1

'' ContentProvider' и ContentResolver' не поддерживают 'JOIN', отчасти потому, что не существует никаких требований, что быть поставщиком поддерживаемый базой данных SQL или чем-либо еще, что понимает, что такое «соединение». – CommonsWare

ответ

1

Да, вы можете сделать это в одном запросе - все данные о контактах фактически хранятся в одной таблице Data, которая содержит все необходимое для контакта, включая CONTACT_ID и DISPLAY_NAME, которые также размещены в таблице Contacts.

Таким образом, вы должны в основном запрос все из таблицы данных в одном запросе, и разобраться в контактах с помощью HashMap из CONTACT_ID в какой-то контакта объекта (или, если вы предпочитаете список деталей).

(Примечание: убедитесь, что вы импортировать следующие классы из пакета ContactsContract только)

Map<Long, List<String>> contacts = new HashMap<Long, List<String>>(); 

String[] projection = {Data.CONTACT_ID, Data.DISPLAY_NAME, Data.MIMETYPE, Data.DATA1, Data.DATA2, Data.DATA3, Data.PHOTO_ID}; 
String selection = Data.MIMETYPE + " IN ('" + Phone.CONTENT_ITEM_TYPE + "', '" + Email.CONTENT_ITEM_TYPE + "')"; 
Cursor cur = cr.query(Data.CONTENT_URI, projection, selection, null, null); 

while (cur != null && cur.moveToNext()) { 
    long id = cur.getLong(0); 
    String name = cur.getString(1); 
    String mime = cur.getString(2); // email/phone/company 
    String data = cur.getString(3); // the actual info, e.g. +1-212-555-1234 
    int type = cur.getInt(4); // a numeric value representing type: e.g. home/office/personal 
    String label = cur.getString(5); // a custom label in case type is "TYPE_CUSTOM" 
    long photoId = cur.getLong(6); 

    String kind = "unknown"; 
    String labelStr = ""; 

    switch (mime) { 
     case Phone.CONTENT_ITEM_TYPE: 
      kind = "phone"; 
      labelStr = Phone.getTypeLabel(getResources(), type, label); 
      break; 
     case Email.CONTENT_ITEM_TYPE: 
      kind = "email"; 
      labelStr = Email.getTypeLabel(getResources(), type, label); 
      break; 
    } 
    Log.d(TAG, "got " + id + ", " + name + ", " + kind + " - " + data + " (" + labelStr + ")"); 

    // add info to existing list if this contact-id was already found, or create a new list in case it's new 
    List<String> infos; 
    if (contacts.containsKey(id)) { 
     infos = contacts.get(id); 
    } else { 
     infos = new ArrayList<String>(); 
     infos.add("name = " + name); 
     infos.add("photo = " + photoId); 
     contacts.put(id, infos); 
    } 
    infos.add(kind + " = " + data + " (" + labelStr + ")"); 
}