ContactsProvider2

article/2025/10/20 13:10:01

本篇不全也不细,只是根据按照个人理解和工作中遇到的问题,总结了个人认为的要点。

1. Android的数据库体系

  • 1.1. 概述
  • 1.2 uri结构

2. ContactsProvider2

  • 2.1. 概述
  • 2.2. Contacts2.db中的表
  • 2.3. ContactProvider2中的实现
  • 2.4. 批量访问

1. Android的数据库体系

1.1. 概述

Android的数据库体系可以分为三个层次:

  1. ContentProvider层;ContentProvider将对数据的增删改查操作进行了抽象,具体实例会注册到AMS中,提供跨进程的服务。ContentProvider可以用于管理各种数据存储源的访问,包括结构化数据(SQLite)和非结构化数据(如图像文件)。
  2. SQLiteDatabase/SQLiteOpenHelper;这部分代码位于“/frameworks/base/core/java/android/database/sqlite/”,ContentProvider要借助于这些框架层的类来和SQLite数据库进行交互。
  3. SQLite数据库;这部分属于native层,代码位于external/sqlite。

ContentProvider不支持线程安全,但SQLite是支持线程安全的(编译前将 宏SQLITE_THREADSAFE 设置为1)。
多个进程可以同时打开一个database,而且可以同时执行SELECT操作,但是同一时间只能有一个进行修改操作。
下面的简图展示了我们使用uri访问database的方式,其中ContentProvider在ActivityManagerService中的register可能是自己所在进程启动时做的,也可能是ActivityManagerService收到uri请求后启动ContentProvider时做的。ContentResolver和ActivityManagerService根据uri中的"authority"来确定要访问的ContentProvider。
在这里插入图片描述

1.2 uri结构

基本结构

[scheme:]scheme-specific-part[#fragment]

进一步划分

[scheme:][//authority][path][?query][#fragment]
path可以有多个,每个用/连接,比如scheme://authority/path1/path2/path3?query#fragment。

query参数可以带有对应的值,也可以不带,如果带对应的值用=表示,如:
scheme://authority/path1/path2/path3?id = 1#fragment,这里有一个参数id,它的值是1
query参数可以有多个,每个用&连接,如
scheme://authority/path1/path2/path3?id = 1&name = xiaofang&age#fragment
这里有三个参数:
参数1:id,其值是:1
参数2:name,其值是:xiaofang
参数3:age,没有对它赋值

在android中,scheme、authority都是必须要有的,而至于path、query和fragment,它们都是选择性的,可以有也可以没有,但顺序不能变,比如:
"path"可不要:scheme://authority?query#fragment
"path"和"query"可都不要:scheme://authority#fragment
"query"和"fragment"可都不要:scheme://authority/path
“path”,“query”,"fragment"都不要:scheme://authority
等等……

终极划分

[scheme:][//host:port][path][?query][#fragment]


2. ContactsProvider2

2.1. 概述

ContactsProvider2是Android一个很成熟的源生组件,用于管理联系人数据相关的存储区。Google对ContactsProvider2有一个比较详细的介绍,下面是相关链接:
https://developer.android.com/guide/topics/providers/contacts-provider

ContactsProvider2管理了两个database,一个是"contacts2.db",另外一个是"profile.db";本篇着重写contacts.db相关的内容。
在这里插入图片描述

2.2. Contacts2.db中的表

“contacts2.db”数据库中存储了联系人、通话记录和Account等数据。
由于联系人的信息字段比较多,包含了号码、地址、Email和头像等信息,所以数据库中的数据表也比较多;为了提高查询速度,还创建了视图和索引;另外还有触发器。

Android P源码中数据表有30多个,视图有11个;这里就不一一列出了,太占地方了,哈哈。
我们需要搞清楚这些表之间的关系,特别是几个存储重要信息的表,下面是几个重要表的ER图
在这里插入图片描述
表“Contacts”中的数据是在数据插入表“raw_contact”之后,在Transaction的回调onCommit调用序列中插入的。

联系人相关的数据并没有存储在raw_contact表中,而是存储在了Data表中;一条raw_contact数据在Data表中对应多条数据。Data表中有15个data字段,每个字段存储的是什么信息要根据列"mimetype_id"来决定,该列的取值来自"account"表的主键"_ID"。
协定类ContactsContract.java中为data字段定义了映射名称类,如下表:

映射类数据类型备注
ContactsContract.CommonDataKinds.StructuredName与该数据行关联的raw contact的姓名数据。一位raw contact只有其中一行。
ContactsContract.CommonDataKinds.Photo与该数据行关联的raw contact的主要照片。一位raw contact只有其中一行。
ContactsContract.CommonDataKinds.Email与该数据行关联的raw contact的电子邮件地址。一位raw contact可有多个电子邮件地址。
ContactsContract.CommonDataKinds.StructuredPostal与该数据行关联的raw contact的邮政地址。一位raw contact可有多个邮政地址。
ContactsContract.CommonDataKinds.GroupMembership将raw contact链接到联系人提供程序内某个组的标识符。组是帐户类型和帐户名称的一项可选功能。联系人组部分对其进行了更详细的描述。

以“ContactsContract.CommonDataKinds.Email”和“ContactsContract.CommonDataKinds.StructuredName”为例,前者用于联系人的Email信息,后者用于联系人的名字信息; 它们分别在Data表中有一条记录,而且都使用了“data1”、“data2”和“data3”这三个字段,但是每个字段在两条记录中分别存储了不同的信息,如下图:
在这里插入图片描述


2.3. ContactProvider2中的实现

下面是ContactsProvider2的类继承关系图:
在这里插入图片描述
ContactsProvider2直接继承了AbstractContactsProvider.java这个类,它的很多功能都继承自这个抽象父类,看代码时这个抽象父类的代码也是重点。
ContactsProvider2中定义了UriMatcher对象sUriMatcher,并在static块中进行了初始化:

matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID);
matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA);
...
matcher.addURI(ContactsContract.AUTHORITY, "data", DATA);

ContractsProvider2会将接收到的uri和sUriMatcher进行匹配,即根据uri中的path确定要访问的table。
比如,我们向Data表中增加一条数据记录,那么我们会使用

ContactsContract.Data.CONTENT_URI,即"content://com.android.contacts/data"

insertInTransaction方法使用sUriMatcher进行匹配后返回”DATA”,然后在switch的对应case语句中处理这条增加数据的请求。

由于"contacts2.db"中的表比较多,而App层只是通过uri发送请求,那么相关表直接的数据维护逻辑是在ContactsProvider2中完成的,这也方便了App层的使用。为了维护数据一致性和原子性等,ContactsProvider2.java的增/删/改都使用了事务(Transaction),下面的流程图展示了insert操作的事务处理流程,其他操作类似:
在这里插入图片描述

2.4. 批量访问

可以使用 ContentProviderOperation 类中的方法创建一批访问调用,然后通过 ContentResolver.applyBatch(…) 应用这些调用。如果某次批量修改需执行大量操作,则可能会阻塞其他进程,导致整体用户体验不佳。可以将想执行的修改操作尽量分散到各个集合中,并为一项或多项操作设置挂起点。挂起点是一个 ContentProviderOperation 对象,并且其 isYieldAllowed() 值设置为 true。当ContactsProvider2遇到挂起点时,它会暂停其工作,让其他进程运行,并关闭当前事务。当ContactsProvider2再次启动时,它会继续执行 ArrayList 中的下一项操作,并启动新事务。

挂起点会导致每次调用 applyBatch() 时产生多个事务。因此,应为一组相关数据行的最后一项操作设置挂起点。例如,应该为一组操作中添加raw contact行及其关联数据行的最后一项操作设置挂起点,或者针对一组与某位联系人相关的行的最后一项操作设置挂起点。
挂起点也是一个原子操作单元。无论访问成功还是失败,两个挂起点之间的所有访问均以一个单元的形式呈现。如果不设置任何挂起点,则最小的原子操作即为整个批量操作。如果使用挂起点,则可以防止操作降低系统性能,还可确保部分操作为原子操作。


结束

http://chatgpt.dhexx.cn/article/uR3iP7sq.shtml

相关文章

Android ContactProvider码源解析

Android Contacts源码解析2 4 ContactsProvider模块 1ContactsProvider简介2数据库创建3主要数据库的表结构相互关系 1data表2raw_contacts表3contacts表4mimetypes5其他表 文章转载自:https://blog.csdn.net/kafka_88/article/details/58585607 4,…

Contacts Provider基础

作为四大组件之一的ContentProvider工作中我们很少会用到自己自定义的ContentProvider,用到的最多的就是系统提供的。官方文档提供了两种系统ContentProvider,一种是CalendarProvider,一种是Contacts Provider。今天我们的主角就是Contact Provider。 The Contacts Provider is…

Error: invalid code, hints: [ req_id: * ]

1、问题描述:这个问题是在处理订单支付时需要用户登录遇到的,具体报错信息如下: 2、报错原因: 当前开发者的appid没有支付权限导致 3、解决方案: 需要负责人给分配对应的权限

This application’s bundle identifier does not match its code signing identifier.

今天使用carthage更新第三方后莫名出现真机云心失败,提示 This application’s bundle identifier does not match its code signing identifier. 解决方法: /usr/local/bin/carthage copy-frameworks 进入Building Phases 单击并在New Run Script Phase中添加脚本 将/usr/lo…

Code Sign error: a valid provisioning profile matching the application's Identifier 'com.yourcompany

出现这个错误的原因是因为:appid和provisioning profile不匹配 !有两种解决的办法:重新下载provisioning profile,或者可能因为:生成证书和appid 所用的根证书不同,最好重新都生成然后下载。(这…

ANTD react 手机号(验证码)登陆 + 账号登陆(图形验证码)

这种页面可能是大家常用的,但重写比较费时间,之前没有搜到完整的,在这里自己总结一下,方面复用 代码: <LoginFormformRef{formRef}initialValues{{autoLogin: false}}onFinish{async values > {await handleSubmit(values as LoginParams)}}><Tabs activeKey{type…

Springboot+axios+vue使用VerifyCodeUtils工具类实现验证码图片功能

一、环境准备 ideajava 1.8maven 3.6.3操作系统&#xff1a;window10vue.min.jsaxios.min.js 二、VerifyCodeUtils工具类 import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import ja…

Identity and Authentication - Common Authentication Methods

Username and Passwords This is the most common method of identifying users in the age of Software as a Service (SaaS) 解释上面的图中的步骤&#xff1a; Login Request: POST /login postuser {username: users,password: pws }Find users: SELECT * FROM databa…

iOS code signing identity 配置

PROJECT 和 TARGET 中都要选:code signing identity: 调试统一都选 developer, 发布统一都选 distribution provisioning Profile 也要选. 过期和无效的证书及时删除, 避免 ambiguous 警告. 选择正确的证书配置后仍然报错, clean 一下重启 xcode 还不行~~~重启电脑

Invalid CAPTCHA response. Please try again. (Code: 1201)

项目场景&#xff1a; Invalid CAPTCHA response. Please try again. (Code: 1201) 解决方案&#xff1a; 直接使用隐私浏览器打开即可。

经典的Embedding方法Word2vec

提起Embedding,就不得不提Word2vec,它不仅让词向量在自然语言处理领域再度流行&#xff0c;更为关键的是&#xff0c;自2013年谷歌提出Word2vec以来&#xff0c;Embedding 技术从自然语言处理领域推广到广告、搜索、图像、推荐等深度学习应用领域&#xff0c; 成了深度学习知识…

embedding表示方法及原理

目录 1.前言2.embedding表示方法2.1 word2vec embedding2.2 neural network embedding2.3 graph embedding 3.参考文献 1.前言 近几年embedding的使用及优化在各种比赛、论文中都有很多的应用&#xff0c;使用embedding表示特征的空间表示也在各种应用中确定是一种很有效的特征…

深度学习:词嵌入Embedding

http://blog.csdn.net/pipisorry/article/details/76095118 词嵌入 词嵌入其实就是将数据的原始表示表示成模型可处理的或者是更dense的低维表示&#xff08;lz&#xff09;。 One-hot Embedding 假设一共有个物体&#xff0c;每个物体有自己唯一的id&#xff0c;那么从物体…

什么是embedding(把物体编码为一个低维稠密向量),pytorch中nn.Embedding原理及使用

文章目录 使embedding空前流行的word2vec句子的表达训练样本损失函数输入向量表达和输出向量表达 v w v_{w} vw​ 从word2vec到item2vec讨论环节pytorch中nn.Embedding原理及使用pytorch中nn.Embedding原理及使用一些注意的点 参考 简单来说&#xff0c;embedding就是用一个低维…

讲清楚embedding到底在干什么

要搞清楚embeding先要弄明白他和one hot encoding的区别&#xff0c;以及他解决了什么one hot encoding不能解决的问题&#xff0c;带着这两个问题去思考&#xff0c;在看一个简单的计算例子 以下引用 YJango的Word Embedding–介绍 https://zhuanlan.zhihu.com/p/27830489 On…

一文读懂Embedding

文章目录 一、**什么是Embedding&#xff1f;**二、One-Hot编码三、**怎么理解Embedding****四、Word Embedding** 一、什么是Embedding&#xff1f; “Embedding”直译是嵌入式、嵌入层。 简单来说&#xff0c;我们常见的地图就是对于现实地理的Embedding&#xff0c;现实的…

Embedding的理解

Embedding 嵌入&#xff0c;我们可以将其理解为一种降维行为。可以将高维数据映射到低维空间来解决稀疏输入数据的问题。 它主要有以下三个目的&#xff1a; 在 embedding 空间中查找最近邻&#xff0c;这可以很好的用于根据用户的兴趣来进行推荐。作为监督性学习任务的输…

BERT的三个Embedding详解

BERT将输入文本中的每一个词&#xff08;token)送入token embedding层从而将每一个词转换成向量形式 两个嵌入层&#xff0c;segment embeddings和 position embeddings token embedding token embedding 层是要将各个词转换成固定维度的向量。在BERT中&#xff0c;每个词会被…

Embedding层的理解

Embedding层的理解 转载自&#xff1a;原文&#xff1a;深入理解 Embedding层的本质_罗小丰同学的博客-CSDN博客_embedding层 首先&#xff0c;我们有一个one-hot编码的概念。 假设&#xff0c;我们中文&#xff0c;一共只有10个字。。。只是假设啊&#xff0c;那么我们用0-…

Embedding理解与代码实现

Embedding 字面理解是 “嵌入”&#xff0c;实质是一种映射&#xff0c;从语义空间到向量空间的映射&#xff0c;同时尽可能在向量空间保持原样本在语义空间的关系&#xff0c;如语义接近的两个词汇在向量空间中的位置也比较接近。 下面以一个基于Keras的简单的文本情感分类问…