5,合并联系人
合并联系人有2个界面,只是一个是自动合并,一个是手动合并而已,查询以及合并流程完全相同。界面如下,
架构图如下,
5.1 查找过程
MergeallActivity是在PeopleActivity中启动的,
startActivity(new Intent(PeopleActivity.this, MergeallActivity.class));
MergeallActivity的构造方法如下,
mQueryTask = new QueryAllRepeartContactsTask(this);
mMode = Query_Mode.query;
mCompleted = false;
mQueryTaskpart = new QuerypartRepeartContactsTask(this);
Query_Mode是内部枚举,定义如下,
private enum Query_Mode{query, update}
mMode 是枚举的query
private Query_Mode mMode = Query_Mode.query;
QueryAllRepeartContactsTask和 QuerypartRepeartContactsTask是MergeallActivity的内部类,继承于WeakAsyncTask,主要用于异步查询。
onCreate方法除了加载布局,还调用了MergeAll方法进行查询,
MergeAll();
MergeAll调用流程图如下,
MergeAll方法主要逻辑如下,
if(mQueryTaskpart != null){
mQueryTaskpart.execute();
}
调用QuerypartRepeartContactsTask的execute方法进行异步查询。
QuerypartRepeartContactsTask的doInBackground方法如下,
ContentResolver resolver = ((MergeallActivity)target).mContext.getContentResolver();
ArrayList<MatrixCursor> targetList = new ArrayList<MatrixCursor>();
targetList = MergeContactCursorUtils.getPartDuplicateContacts(resolver, this ,mDefaultCountryIso);
return targetList;
调用MergeContactCursorUtils的getPartDuplicateContacts方法进行查询,然后将查询结果封装在MatrixCursor 的ArrayList中进行返回。
getSameNameContactsIds方法主要逻辑如下,
1,构造查询语句,
StringBuilder sb = new StringBuilder();
sb.append(MergeContantQuery.sameNameSQL);
sb.append(" ORDER BY dataone.raw_contact_id, dataone.display_name");
MergeContantQuery的sameNameSQL方法如下,
public static String sameNameSQL =
"SELECT DISTINCT dataone.raw_contact_id" + " FROM view_data as dataone"
+ " WHERE dataone.display_name IN" + " (SELECT raw_contacts.display_name FROM
raw_contacts WHERE raw_contacts.deleted != 1" + " AND raw_contacts.account_id IN"
+" (SELECT _id from accounts WHERE account_type = '"
+ SimContactUtility.ACCOUNT_TYPE_LOCAL+ "'"+ " OR account_type IS NULL)"
+ " GROUP BY raw_contacts.display_name having count(display_name) >1)"
+ " AND dataone.mimetype = '" + StructuredName.CONTENT_ITEM_TYPE + "'";
这段查询语句较长,根据Contacts2.db数据库分析.
首先看红色部分,
SimContactUtility的ACCOUNT_TYPE_LOCAL 字符串如下,
public static final String ACCOUNT_TYPE_LOCAL = "com.android.localphone";
因此,红色部分的查询语句意思如下,
从accounts表单中查询account_type类型为"com.android.localphone"或者为空的id。
accounts表单如下,
因此,查询的结果为1.
绿色查询语句的意思如下,
从raw_contacts表中查询出deleted!= 1 并且account_id 为1对应的display_name信息.
Deleted 为1 表示已经删除的联系人。
raw_contacts表 部分如下,
因此,查询的结果为adc.
Group By语句从英文的字面意义上理解就是“根据(by)一定的规则进行分组(Group)”。它的作用是通过一定的规则将一个数据集划分成若干个小的区域,然后针对若干个小区域进行数据处理。
整个sql语句的意思为:从Contacts2.db数据库中查询出至少有2个姓名相同的联系人,并且命名相同的联系人相邻返回。
2,从contacts2.db 数据库中查询结果,获取Cursor对象,
Cursor cursor = null;
try {
cursor = resolver.query(MergeContantQuery.mUri, null, sb.toString(),null, null);
3,调用getRawContactsIds方法将Cursor对应的id保存在mSameNameRawContactsIds中,
do {
Long raw_contact_id = cursor.getLong(0);
if(!rawContactsList.contains(raw_contact_id)){
rawContactsList.add(raw_contact_id);
}
} while (cursor.moveToNext());
cursorToGroupCursor方法主要将相同姓名的联系的MatrixCursor作为一组,注意,通过这个方法,已经将组都分好了。
回看QuerypartRepeartContactsTask的doInBackground方法,
protected ArrayList<MatrixCursor> doInBackground(Activity target, Void... params) {
ContentResolver resolver = ((MergeallActivity)target).mContext.getContentResolver();
ArrayList<MatrixCursor> targetList = new ArrayList<MatrixCursor>();
targetList = MergeContactCursorUtils.getPartDuplicateContacts(resolver, this ,
mDefaultCountryIso);
return targetList;
}
注意,该方法返回的是ArrayList<MatrixCursor>,是经过分组的,而不是MatrixCursor对象。