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 + "]";
}
}