Android获取所有联系人列表(姓名,电子邮件,电话)大约需要一分钟约700个联系人

有什么办法可以缩短这个时间吗? 我正在用光标运行,并采取名称,电话号码和电子邮件

如果我从查询循环中删除电话号码查询,它会在3秒内结束

任何想法我怎么能改善这个查询?

也许我在查询中做错了什么?

(很明显,我正在做asynchronous,但仍然…用户不能等待很长时间)

希望有人可以分享他的想法

这是我的代码

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(); 

下面的59个联系人的代码,我在模拟器上得到了以下结果:

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

好的,这是最好的时间,但平均25-35毫秒(对于59个联系人),在一些onClickcallback中添加以下代码,并运行几次以获得平均时间,在你的情况下,你应该得到30 * 700/59 = 〜300-400 ms,而不是3秒,更不用说一分钟;)

它将Uri设置为在API级别18中添加的Contactables.CONTENT_URI ,但在为前18个API设备构build时可以使用ContactsContract.Data.CONTENT_URI

 List<AddressBookContact> list = new LinkedList<AddressBookContact>(); LongSparseArray<AddressBookContact> array = new LongSparseArray<AddressBookContact>(); 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 = "<b><font color='#ff9900'>"; final String cOff = "</font></b>"; Spanned l1 = Html.fromHtml("got " + cOn + array.size() + cOff + " contacts<br/>"); 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<AddressBookContact>(this, android.R.layout.simple_list_item_1, list)); ll.addView(lv); new AlertDialog.Builder(this).setView(ll).setPositiveButton("close", null).create().show(); 

帮手AddressBookContact类:

 class AddressBookContact { private long id; private Resources res; private String name; private LongSparseArray<String> emails; private LongSparseArray<String> 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<String>(); } emails.put(type, address); } public void addPhone(int type, String number) { if (phones == null) { phones = new LongSparseArray<String>(); } phones.put(type, number); } } 

您可以检索查询中的所有列:

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

这使得数据处理慢得多。 如果你定义了一个真正需要检索的列数组,它将会更快。

试试这个代码,使用进度dialouge

 public void getAllContacts() { new AsyncTask<String, String, ArrayList<UserInfo>>() { ArrayList<UserInfo> infos = new ArrayList<>(); @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected ArrayList<UserInfo> 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<UserInfo> aVoid) { super.onPostExecute(aVoid); // EventBus.getDefault().post(aVoid); } }.execute(); }