Android busca toda la lista de contactos (nombre, correo electrónico, teléfono) tarda más de un minuto para unos 700 contactos

¿Hay alguna forma de acortar esta vez? Me estoy ejecutando con el cursor y toma el nombre, los números de teléfono y los correos electrónicos

si elimino la consulta de números de teléfono del bucle de consulta, termina en 3 segundos

¿Alguna idea de cómo puedo mejorar esa consulta?

Tal vez estoy haciendo algo mal en mi consulta?

(Obviamente lo hago asincrónico, pero aún así … es un tiempo muy largo que un usuario no puede esperar)

Espero que alguien pueda compartir sus pensamientos sobre esto

este es mi código

ContentResolver cr = getContentResolver(); Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); if (cur.getCount() > 0) { while (cur.moveToNext()) { AddressBookEntity adr = new AddressBookEntity(); String id = cur.getString(cur .getColumnIndex(ContactsContract.Contacts._ID)); String name = cur .getString(cur .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); adr.fullName = name; Cursor emailCur = cr .query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[] { id }, null); while (emailCur.moveToNext()) { // This would allow you get several email addresses // if the email addresses were stored in an array String email = emailCur .getString(emailCur .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)); if (!Utils.IsNullOrEmptyString(email)) { adr.email = email; } } emailCur.close(); if (Integer .parseInt(cur.getString(cur .getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) { Cursor pCur = cr .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null); int phoneIndex = 0; while (pCur.moveToNext()) { String number = pCur.getString(pCur .getColumnIndex(Phone.NUMBER)); String country = Utils.GetCountryFromNumber( number, app); number = Utils.GetFullPhoneNumber(number, app); if (phoneIndex == 0) { if (!Utils.IsNullOrEmptyString(number)) { adr.contactAdressBookId = id; adr.phoneNumber = number; adr.userInsertedId = app.userCred.userId; adr.country = country; myContacts.add(adr); } } else { if (!Utils.IsNullOrEmptyString(number)) { AddressBookEntity adrMore = new AddressBookEntity(); adrMore.fullName = adrMore.fullName; adrMore.country = adrMore.country; adrMore.email = adrMore.email; adrMore.phoneNumber = number; adrMore.contactAdressBookId = id; adrMore.country = country; myContacts.add(adrMore); } } } pCur.close(); } } cur.close(); 

con el siguiente código para 59 contactos obtuve los siguientes resultados en el emulador:

  D ╔══════ query execution stats ═══════ D ║ got 59 contacts D ║ query took 0.012 s (12 ms) D ╚════════════════════════════════════ 

bien, ese fue el mejor momento, pero el promedio es de 25-35 ms (para 59 contactos), agregue el siguiente código en alguna callback onClick y ejecute varias veces para obtener el tiempo promedio, en su caso debería obtener 30 * 700/59 = ~ 300-400 ms, no 3 segundos, y mucho menos un minuto;)

usa Uri configurado en Contactables.CONTENT_URI agregado en API nivel 18, pero puede usar ContactsContract.Data.CONTENT_URI cuando comstack para dispositivos pre 18 API

 List list = new LinkedList(); LongSparseArray array = new LongSparseArray(); long start = System.currentTimeMillis(); String[] projection = { ContactsContract.Data.MIMETYPE, ContactsContract.Data.CONTACT_ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Contactables.DATA, ContactsContract.CommonDataKinds.Contactables.TYPE, }; String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)"; String[] selectionArgs = { ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE, }; String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE; Uri uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI; // we could also use Uri uri = ContactsContract.Data.CONTENT_URI; // ok, let's work... Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder); final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE); final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID); final int nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); final int dataIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA); final int typeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.TYPE); while (cursor.moveToNext()) { long id = cursor.getLong(idIdx); AddressBookContact addressBookContact = array.get(id); if (addressBookContact == null) { addressBookContact = new AddressBookContact(id, cursor.getString(nameIdx), getResources()); array.put(id, addressBookContact); list.add(addressBookContact); } int type = cursor.getInt(typeIdx); String data = cursor.getString(dataIdx); String mimeType = cursor.getString(mimeTypeIdx); if (mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) { // mimeType == ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE addressBookContact.addEmail(type, data); } else { // mimeType == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE addressBookContact.addPhone(type, data); } } long ms = System.currentTimeMillis() - start; cursor.close(); // done!!! show the results... int i = 1; for (AddressBookContact addressBookContact : list) { Log.d(TAG, "AddressBookContact #" + i++ + ": " + addressBookContact.toString(true)); } final String cOn = ""; final String cOff = ""; Spanned l1 = Html.fromHtml("got " + cOn + array.size() + cOff + " contacts
"); Spanned l2 = Html.fromHtml("query took " + cOn + ms / 1000f + cOff + " s (" + cOn + ms + cOff + " ms)"); Log.d(TAG, "\n\n╔══════ query execution stats ═══════" ); Log.d(TAG, "║ " + l1); Log.d(TAG, "║ " + l2); Log.d(TAG, "╚════════════════════════════════════" ); SpannableStringBuilder msg = new SpannableStringBuilder().append(l1).append(l2); LinearLayout ll = new LinearLayout(this); ll.setOrientation(LinearLayout.VERTICAL); TextView tv = new TextView(this); tv.setTextSize(20); tv.setBackgroundColor(0xff000033); tv.setPadding(24, 8, 24, 24); tv.setText(msg); ll.addView(tv); ListView lv = new ListView(this); lv.setAdapter(new ArrayAdapter
(this, android.R.layout.simple_list_item_1, list)); ll.addView(lv); new AlertDialog.Builder(this).setView(ll).setPositiveButton("close", null).create().show();

la clase auxiliar AddressBookContact :

 class AddressBookContact { private long id; private Resources res; private String name; private LongSparseArray emails; private LongSparseArray phones; AddressBookContact(long id, String name, Resources res) { this.id = id; this.name = name; this.res = res; } @Override public String toString() { return toString(false); } public String toString(boolean rich) { SpannableStringBuilder builder = new SpannableStringBuilder(); if (rich) { builder.append("id: ").append(Long.toString(id)) .append(", name: ").append("\u001b[1m").append(name).append("\u001b[0m"); } else { builder.append(name); } if (phones != null) { builder.append("\n\tphones: "); for (int i = 0; i < phones.size(); i++) { int type = (int) phones.keyAt(i); builder.append(ContactsContract.CommonDataKinds.Phone.getTypeLabel(res, type, "")) .append(": ") .append(phones.valueAt(i)); if (i + 1 < phones.size()) { builder.append(", "); } } } if (emails != null) { builder.append("\n\temails: "); for (int i = 0; i < emails.size(); i++) { int type = (int) emails.keyAt(i); builder.append(ContactsContract.CommonDataKinds.Email.getTypeLabel(res, type, "")) .append(": ") .append(emails.valueAt(i)); if (i + 1 < emails.size()) { builder.append(", "); } } } return builder.toString(); } public void addEmail(int type, String address) { if (emails == null) { emails = new LongSparseArray(); } emails.put(type, address); } public void addPhone(int type, String number) { if (phones == null) { phones = new LongSparseArray(); } phones.put(type, number); } } 

Usted recupera todas las columnas en su consulta:

 Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); 

Esto hace que el procesamiento de datos sea mucho más lento. Si define una matriz de columnas que realmente necesita recuperar, será mucho más rápido.

prueba este código, usa un dialouge de progreso

 public void getAllContacts() { new AsyncTask>() { ArrayList infos = new ArrayList<>(); @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected ArrayList doInBackground(String... params) { ContentResolver contactResolver = context.getContentResolver(); Cursor cursor = contactResolver.query(ContactsContract.Contacts.CONTENT_URI, new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER }, null, null, null); if(cursor.getCount()>0) while ( cursor.moveToNext()) { String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); // String photoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI)); String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); // String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); Log.d("TAG", " Name: " + displayName); if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) { Cursor pCur = contactResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { contactId }, null); while (pCur.moveToNext()) { String phone = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); String type = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE)); String s = (String) ContactsContract.CommonDataKinds.Phone.getTypeLabel(context.getResources(), Integer.parseInt(type), ""); Log.d("TAG", s + " phone: " + phone); } pCur.close(); } Cursor emailCursor = contactResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[] { contactId }, null); while (emailCursor.moveToNext()) { String phone = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)); int type = emailCursor.getInt(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE)); String s = (String) ContactsContract.CommonDataKinds.Email.getTypeLabel(context.getResources(), type, ""); Log.d("TAG", s + " email: " + phone); } emailCursor.close(); } cursor.close(); return null; } @Override protected void onPostExecute(ArrayList aVoid) { super.onPostExecute(aVoid); // EventBus.getDefault().post(aVoid); } }.execute(); }