上篇文章讲解了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表
/** 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))
protected long insertContact(SQLiteDatabase db, long rawContactId) {
mSelectionArgs1[0] = String.valueOf(rawContactId);
computeAggregateData(db, mRawContactsQueryByRawContactId, mSelectionArgs1, mContactInsert);
return mContactInsert.executeInsert();
}
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 (?,?,?,?,?,?,?,?,?,?)";
mContactInsert = db.compileStatement(ContactReplaceSqlStatement.INSERT_SQL);