Android对联系人(Contact)存储的设计对初学者来说可以算是非常复杂,如果翻看源代码,可以看到android.provider.ContactContract的代码就接近万行,内部子类、接口非常多。下面根据官方文档,介绍三个主要的子类。


ContactsContract.Contacts

关联contacts表,存储按每个联系人聚合的各种信息。

插入

无法显式创建联系人(即显式地要求数据库新增一个新的联系人记录)。当一行联系人数据插入后,系统provider会首先尝试查找代表相同联系人的行。如果找到,则新插入数据的CONTACT_ID列会被设置为数据库中原有的行的_ID值;如果没有找到匹配的,则会自动插入一个新的联系人并将新数据行的_ID值设置为新联系人的CONTACT_ID

修改

只有以下确定的列是应用程序可以修改的:TIMES_CONTACTED, LAST_TIME_CONTACTED, STARRED, CUSTOM_RINGTONE, SEND_TO_VOICEMAIL。在Contact中修改这些字段,相关的其他表中的值也会发生改变。

删除

删除操作要小心,因为在这里删除一个联系人将导致它的所有成分都被删除。并且,相关的同步适配器会就本次删除发出通知,从而数据会从后端存储中移除。

查询

  • 如果需要读一个单独的联系人,那么应该考虑使用CONTENT_LOOKUP_URI 而不是 CONTENT_URI

  • 如果需要通过电话号码查找特定的联系人,应该考虑使用专为这种场景进行优化的PhoneLookup.CONTENT_FILTER_URI

  • 如果需要根据部分名称查找特定的联系人,使用CONTENT_FILTER_URI。【译者注:这里的URI和上一条并不一样,注意它们的类名限定。】

  • 如果需要根据一些数据元素(例如,Email,地址,昵称)来进行查询,应该对ContactsContract.Data表进行查询。返回的结果会包含联系人的ID、名字,等等。


ContactContract.Data

包含关于data表的常量,该表存储与联系人原始数据绑定的一些信息。data表的每一行都只用来存储一个单一方面的信息(例如,电话号码)以及相关的元数据(例如,这是一个工作电话还是家庭电话)。

数据种类

data表是一个通用表,可以存储任何种类的数据。对于一个特定的行,其存储的数据种类由该行的MIMETYPE列值指定,该值将决定通用列DATA1~DATA15所代表的含义。举个例子,如果数据种类是Phone.CONTENT_ITEM_TYPE,那么DATA1存储的是电话号码;但如果数据种类是Email.CONTENT_ITEM_TYPE,则DATA1存储的是电子邮箱的地址。同步适配器和应用程序可以引入自己的特有数据种类

ContactContract类定义了一小部分预定义的数据种类,这些常量值放在ContactsContract.CommonDataKinds类中。为方便起见,这些类还为DATA1等列定义了自己特有的别名,例如Phone.NUMBER就等同于DATA1。

DATA1是一个索引列,它应该被用于存储在查询时通常使用频率最高的数据元素。比如,存储电子邮箱的行,应该使用DATA1来存储电子邮箱的地址,而DATA2等列可以用来存储邮箱地址的类型等辅助信息。

按惯例,DATA15字段一般用于存储BLOB(二进制数据)。

对于指定的账户类型,其同步适配器必须能够正确处理关联的联系人中所有的数据种类,否则会造成数据的丢失或损坏。

类似地,开发者应该避免引入其他账户类型的数据种类。例如,如果开发者将一行“最喜欢的歌”加入一个属于Google 账户的联系人里,这条数据不会被同步到服务器上,因为Google同步适配器不知道如何处理这样的数据。因此,引入新的数据种类通常意味着要使用新的账户,和新的同步适配器。

批量操作

数据行可以使用传统的insert(Uri, ContentValues),update(Uri, ContentValues, String, String[])和delete(Uri, String, String[])方法进行新增/修改/删除操作,然而,ContentProviderOperation提供了新的批量处理的机制,这在多数情况下都会是更好的选择。一个批次里的所有操作都会在单个事务中完成,这将确保手机端和服务器端数据的一致性。同时,基于批量处理的途径会更为有效:不仅仅是多个操作在单个事务中执行所节省的数据库的时间,还包括在应用程序进程和系统provider进程之间发送命令、切换进程时多次保存上下文花费的大量时间。

但这样带来的一个问题是,大批次的处理在执行期间可能会锁定数据库较长时间,从而阻碍其他应用程序访问数据库,潜在地,可能导致应用出现ANR(Application Not Responding应用程序无响应)对话框。

要避免这样的锁定,可以在批量处理操作中插入“让步点”(yield points)。让步点指示provider在执行下一步操作之前可以提交已经做的修改,让步给其它请求(其他应用程序读写),打开另一个事务并继续处理未完成的操作。让步点不会自动提交操作,除非有其它的应用程序请求在等待数据。通常同步适配器应该在批次中每一个联系人操作序列之前插入一个让步点。

译者注:关于批处理的示例代码,可以查看官网API,或在本博留言。


ContactsContract.RawContacts

定义raw contact表相关常量,该表包含对每个同步账户的每个联系人的信息。同步适配器和联系人管理应用一般会使用该API。

聚合(汇总)

每当一行联系人被插入或修改,provider就将检查新增的联系人信息是否和已存在的联系人信息匹配,如果是,则合并他们。这样的聚合会通过ContactsContract.RawContacts表的CONTACT_ID字段改变而反映出来,而这个字段指向汇总的联系人信息。

每次修改名称、机构、电话号码、电子邮箱、昵称,都会触发这样的聚合事件。

更多相关文章

  1. Android存储之SharePreferences
  2. android数据单位dp,px和sp
  3. 程序员挑战高薪,你必须会的十大面试题《一》
  4. Android中的文件存储数据方式 .
  5. 用volley从网页获取json数据
  6. 关于Android(安卓)Manifest中的
  7. Android如何通过shareduserid获取系统权限
  8. 一篇胎死腹中的Android文章——Dex文件结构解析
  9. 如何查看android的avd中的sqlite数据库的表

随机推荐

  1. Android BroadcastReceiver介绍
  2. Android中禁用屏幕旋转
  3. A20红外遥控器与Android功能的适配
  4. Android(安卓)4.0 多平台界面支持原理分
  5. Android canvas clip 参数解释
  6. Android系统启动执行jar程序
  7. S3C6410(M8用的) 移植Android 内核
  8. Android SafeMode 解析
  9. ImageView的android:adjustViewBounds属
  10. 安卓开发学习道路上觉得不错的学习网站