您的位置:首页 > 移动开发 > Android开发

Android联系人模块分析(二)

2012-10-19 14:12 369 查看
上篇文章讲解了ContentsProvider的基本结构,本篇文章结合实际的联系人模块操作的例子来讲解联系人模块的使用。

下图为联系人模块中的表结构,各个表项中字段信息,可以参考上篇文章对ContactscProvder的分析中所描述的,在ContactsContract.java文件中定义了各个数据表的结构、Uri等信息。ContactsProvider数据库的三个主要的数据表结构信息如下图:



这三张表是联系人数据库的最主要的数据表,其他的数据只是提供一些辅助功能,我们先详细介绍这三张表的结构和使用方法。

从上图我们可以看书Contacts表和raw contact表是一对多的关系,Contacts表是对raw contact表记录的聚合,即Contacts表中是没有账户(Account)的概念的,而raw contact表是联系人特定账户的的概要信息,Data表则存储了联系人的详细信息,比如email、电话号码等。

下面我们就详细介绍一下上述三张数据表的结构和使用方法:

一、raw contact表

raw contact表描述了联系人每个账户下的数据,根据账户名和账户类型字段进行区分。即同一个联系人可能在raw contact表中有多个记录,每个记录分属于不同的账户。所以一个contact id可能对应多一个raw contact id,这也是笔者屡次被问及的一个问题,为什么一个contact id会对应多个raw contact id,相信读者看到这里就会知道该问题的答案了。从这里我们也发现android是允许一个联系人绑定多个账户的。

需要注意的字段为ACCOUNT_NAME,ACCOUNT_TYPE,DELETED、VERSION。

ACCOUNT_NAME和ACOUNT_TYPE我就不详细描述了,DELETED标志位的作用是,当删除一条用户记录时,可以暂时再内部维护一条删除状态的记录,待该账户的server端删除完毕后,再从本地删除,其实用户可以不必关心该字段的内部机制,只需要注意在查询raw contact表时,可以根据DELETED字段过滤掉已删除的记录。VERSION字段也是一个很有用的字段,可以根据该字段来确定联系人信息是否发生变化,如果您本地保存了联系人信息,那么就可以根据VERSION信息来和系统数据库的联系人信息进行比较,来确定是否需要做UPDATE操作。

二、data表

data表存储了联系人的具体信息,比如电话、email等信息,从上图我们可以看书每个raw contact表中的记录会对应多个data信息,这不难理解,一个联系人可能有多个电话号码,多个email,这些信息是如何存储再data表中的呢?其实不难解决这个问题,定义一个专门的描述字段用来定义该记录的类型,即MIME TYPE,然后根据MIME TYPE来区分该记录的类型。然后每种信息都会有一个自己的类型,比如phone记录,在ContactsContract中的Phone类中进行了定义:
/** MIME type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";


从上述的注释可以看出该MIME type的定义是用来将Phone信息存储在data表中的。这样如果需要判断data表中某条记录是否为电话号码信息,可以如下:
if(Phone.CONTENT_ITEM_TYPE.equals(mime))

三、Contacts表
Contacts表是对raw contact表按照account type和account name进行的聚合。Contacts表的聚合逻辑在ContactAggregator.java文件中,该类中定义了一个成员方法:
protected long insertContact(SQLiteDatabase db, long rawContactId) {
mSelectionArgs1[0] = String.valueOf(rawContactId);
computeAggregateData(db, mRawContactsQueryByRawContactId, mSelectionArgs1, mContactInsert);
return mContactInsert.executeInsert();
}


这个方法就是用来往Contacts表中插入数据的,该方法被出发调用的时机为:raw contact表有新插入记录,ContactsProvider的onCommit事件等。上述插入Contacts表的SQL语句为:
String INSERT_SQL =
"INSERT INTO " + Tables.CONTACTS + " ("
+ Contacts.NAME_RAW_CONTACT_ID + ", "
+ Contacts.PHOTO_ID + ", "
+ Contacts.PHOTO_FILE_ID + ", "
+ Contacts.SEND_TO_VOICEMAIL + ", "
+ Contacts.CUSTOM_RINGTONE + ", "
+ Contacts.LAST_TIME_CONTACTED + ", "
+ Contacts.TIMES_CONTACTED + ", "
+ Contacts.STARRED + ", "
+ Contacts.HAS_PHONE_NUMBER + ", "
+ Contacts.LOOKUP_KEY + ") " +
" VALUES (?,?,?,?,?,?,?,?,?,?)";


生成SQL statement的语句为:
mContactInsert = db.compileStatement(ContactReplaceSqlStatement.INSERT_SQL);


ok,读者可以根据我上述列举的点仔细研读一下Contacts表记录的插入过程。对应用程序而言,Contacts表大多数字段都是只读的,由ContactsProvider来维护该表的信息,如果您需要所有联系人的信息,且不区分账号类型和账号名称,您可以从该表中取出所有的记录。

下面有几道思考题,读者可以试着完成,我后续会详细的结合实例再来分析这几张表的内容,以及其他几张辅助表的使用。

1、取出所有无手机号码的联系人(不区分account type和account name);
2、取出特定联系人的手机号码和email信息;
3、读出所有账号类型为空的联系人;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: