1 首先我们要明白,在2.0后,联系人数据库大改了,导致之前的查询可能失效,深入了解请参考 点击打开链接
2 我们在查询联系人一般都是 ContactsContract.Contacts.CONTENT_URI(2.0后谷歌建议的类),可是在此类只可以查询到姓名,并不能查询到手机号码,如果需要需要手机号码(绝大多数情况下都需要查询),这个时候我们就需要在循环内查询Phone表,这样循环里面嵌套循环,循环的开关游标,如果联系人少还好说, 如果多,就会变的非常卡卡,本人100+联系人,在2G内存S3下都很卡。所以我们要找个方法来解决他。
3 我们需要明白如下,系统是以姓名作为唯一标示,如果 系统存在 (习,10086,李 10000,王 10010,习 110) 这几个联系人。在系统通讯录下是3个,因为系统会自动合并
在QQ通讯录,360通讯录,百度通讯录都是3个,而且我们通过ContactsContract.Contacts.CONTENT_URI也是3个,
但是通过Phone查询是4个,通过RawContact查询的是4个,通过Phone和RawContact查询的是联系人的详细信息,是有电话号码的,但是通 过ContactsContract.Contacts.CONTENT_URI是没有电话号码的,所以我们为了提高效率,必须考虑是否查询Phone这个url
4 通过phone查询之后,联系人要比系统显示的多,且姓名相同的没有自动合并,这就需要我们收到处理了
5 关键在于add2List方法,以姓名为唯一标示,将联系人合并,这样只需要一个循环,效率大为提高,而且和QQ,360,系统一样的效果
6 本人的做法,开机启动一个服务,这个服务去查询联系人数据,然后放到application中,因为这个服务一直在后台运行,所以进入到联系人界面非常非常快(但是360和QQ电脑管家可以禁止我的开机启动,和服务被kill后不能再次重新启动,方法是我们可以比360更流氓,开个闹钟,不停发广播,监听各种广播事件........)
import android.provider.ContactsContract.CommonDataKinds.Phone;
/** * 查询联系人 */ private void queryContact() { String[] projection = { Phone._ID, Phone.DISPLAY_NAME, Phone.DATA1, Phone.CONTACT_ID, "sort_key", Phone.PHOTO_ID }; // 查询的列 asyncQuery.startQuery(0, null, Phone.CONTENT_URI, projection, null, null, "sort_key COLLATE LOCALIZED asc"); // 按照sort_key升序查询 }
class MyAsyncQueryHandler extends AsyncQueryHandler { public MyAsyncQueryHandler(ContentResolver cr) { super(cr); } @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { switch (token) { case 0:// 查询联系人 if (cursor != null && cursor.getCount() > 0) { list = new ArrayList<ContactBean>(); while (cursor.moveToNext()) { ContactBean cb = new ContactBean(); cb.contactId = cursor.getInt(0); cb.displayName = cursor.getString(1); String number = cursor.getString(2); if (number.contains("+86")) { cb.phoneNum = number.substring(3, number.length()); } else { cb.phoneNum = number; } cb.contactId = cursor.getInt(3); cb.sortKey = cursor.getString(4); //if (null != cb.displayName) {// 将姓名转换为拼音,需要pinyin4j-2.5.0.jar // cb.pinyin = Tools.chineseToPinYin(cb.displayName); //} cb.photoId = cursor.getLong(5); cb.list.add(number); //add2List(list, cb); Log.e("MainActivity", cb.toString()); } //setContactAdapter(list); } break; } } }
/** * 以姓名为唯一标示,将姓名相同的号码联系人合并 * * @param list * @param ContactBean */ public void add2List(ArrayList<ContactBean> list, ContactBean cb) { int size = list.size(); for (int i = 0; i < size; i++) { if (list.get(i).displayName.equals(cb.displayName)) { int length = cb.list.size(); for (int j = 0; j < length; j++) { list.get(i).list.add(cb.list.get(j)); } return; } } list.add(cb); }
public class ContactBean { public int contactId;// 联系人ID public int selected; public String displayName;// 姓名 public String phoneNum;// 显示的电话号码 public String sortKey;// sortKey public Long photoId;// 头像ID public String lookUpKey;// lookUpKey public String pinyin;// 姓名的中文拼音 public ArrayList<String> list;// 存储姓名的集合 public ContactBean() { list = new ArrayList<String>(); } public ContactBean(int contactId, int selected, String displayName, String phoneNum, String sortKey, Long photoId, String lookUpKey, String pinyin, ArrayList<String> list) { super(); this.contactId = contactId; this.selected = selected; this.displayName = displayName; this.phoneNum = phoneNum; this.sortKey = sortKey; this.photoId = photoId; this.lookUpKey = lookUpKey; this.pinyin = pinyin; this.list = list; } @Override public String toString() { return "ContactBean [contactId=" + contactId + ", selected=" + selected + ", displayName=" + displayName + ", phoneNum=" + phoneNum + ", sortKey=" + sortKey + ", photoId=" + photoId + ", lookUpKey=" + lookUpKey + ", pinyin=" + pinyin + ", list=" + list + "]"; } }