内容提供者-Content Provider

时间:2022-01-02 11:56:56

内容提供者-Content Provider

Content providers管理对结构化数据集的使用.它们封装数据,并提供了数据安全的机制.Content providers是从一个进程连接另一个进程中的数据的标准接口. 

当你想使用一个content provider中的数据,你需在你的应用的Context 中使用ContentResolver对象作为客户端与provider 进行通讯.ContentResolver对象与provider对象通讯,provider是实现ContentProvider的类.Provider对象接收客户端发来的请求,执行请求的动作,返回结果. 

如果你不想把你的数据共享给其它应用,你不需开发你自己的provider.然而,你需要自己的provider来在你的应用中提供自定义搜索建议.如果你需要从你的应用中考贝复杂的数据或文件粘贴到其它应用中,你也需要提供自己的provider 

Android自己包含了管理音频,视频,图像,个人通讯录等数据的content providers.你可以从android.provider 包的参考文档中爪到它们.这些providers 可以被所有的android应用使用,但可能带有一些限制. 

Content Provider 基础

一个content provider 管理对*数据仓库的使用.一个provider是一个Android应用的一部分,应用一般提供它自己的UI来操作数据.然而,content providers主要是为了给其它应用使用,其它的应用使用provider客户端对象来操作providerproviders provider客户端一起提供了一致的,标准的接口来操作用于进程间通讯的数据并保处数据的安全性. 

本节讲解以下基础知识:

· content providers如何工作.

· content provider取得数据的API.

· content provider插入,更新以及删除数据的API.

· 其它有助于使用providersAPI.

概述

一个content provider代表了面向外部应用的数据,这些数据看起来就像关系型数据库中的一个或多个table.一行代表某种数据类型的一个实例,一列代表这个实例的一个属性或字段.

举个例子,Android平台中的一个内建的provider是用户词典,它存储了用户想保存的非标准词的拼写.表演示了数据在provider的表中可能看起来的样子:

Table 1: 简单用户词典表

word

app id

frequency

locale

_ID

mapreduce

user1

100

en_US

1

precompiler

user14

200

fr_FR

2

applet

user2

225

fr_CA

3

const

user1

255

pt_BR

4

int

user5

100

en_UK

5

在上表中,每行代表了一个不能在标准字典中找到的词.每一列代表了这个词了一个属性.列头是存储在provider中的列的名字.要引用一行的locale属性,需引用locale 列.对于这个provider_ID列作为"主键"列,provider会自动管理它.

注:一个provider不是必须具备主键的,并且也不是必须使用_ID 作为主键的列名来引用一行.然而,如果你把一个provider绑定到一个ListView就必须有一个列名叫做_ID.此需求将在显示查询结果一节中有详细的解释.

操作一个provider

应用使用ContentResolver客户端对象来操作content provider中的数据.此对象具有一些与provider 对象中同名的方法,provider对象指的是某个ContentProvider具体派生类的实例.ContentResolver 的方法们提供了对存储数据的基本的"CRUD" (增删改查)功能.

ContentResolver 对象处于客户端应用的线程中,ContentProvider 对象位于另外的进程并且自动处理进程间通讯. ContentProvider 也代表了数据层与可视层之间的一个抽象层.

注:要使用一个provider,你的应用通常需要在manifest请求一些权限这将在Content Provider 一节中进行更详细的讲解.

举个例子,要从用户词典Provider中获取取单词和它们的locale列表,你需调用ContentResolver.query()query() 方法会调用用户词典中的ContentProvider.query() 方法.下面的代码演示了ContentResolver.query() 调用:

// 查询用户词典并返回结果
mCursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,   // 单词表的content URI
    mProjection,                        // 每行要返回的列们
    mSelectionClause                    // Selection的条件
    mSelectionArgs,                     // Selection的条件
    mSortOrder);                        // 返回各行要如何排序

2展示了query(Uri,projection,selection,selectionArgs,sortOrder) 的参数们如何与一个SQL SELECT语句匹配:

Table 2: Query() SQL 查询的对比

query() argument

SELECT keyword/parameter

Notes

Uri

FROM table_name

Uri 对应provider 中叫做table_name的表.

projection

col,col,col,...

projection 是每行要包含的列们

selection

WHERE col = value

selection 指定了一些选择条件

selectionArgs

(不能对应.替换selection参数各类似于? 的占位符)

sortOrder

ORDER BY col,col,...

sortOrder 指定排序方式


 

Content URIs

content URI 是一个标志provider中的数据的URI.Content URI中包含了整个provider的以符号表示的名字(它的authority) 和指向一个表的名字(一个路径).当你调用一个客户端的方法来操作一个provider中的一个表,指向表的content URI是参数之一. 

常量CONTENT_URI 中包含了用户词典table的content URI.ContentResolver 对象分析出URI的authority,并使用它与一个已知provider组成的系统表中的authority进行对比来"解决"provider.ContentResolver之后就会派送查询参数给正确的 provider. 

ContentProvider使要长content URI的路径辨别分来选择要操作的表.通常一个provider中要暴露的每个表都具有一个路径. 

在上面的例子的代码中,"词典"表的全URI是: 

content://user_dictionary/words

user_dictionary部分是provider的 authority,words部分是表的路径.字符串 content:// (the scheme) 总是要存在,它表示引用一个content URI.

很多provider允许你通过在URI的末尾增加一个ID操作表中一个单独的行.例如,要从用户词典中获取_ID是4的一行,你可要行使用这样的content URI: 

Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

当你要获取多行然后更新或删除其中一时,你经常要使用的是id值. 

注:Uri和Uri.Builder类包含由字符串构建格式正确的Uri对象的简便的方法们.ContentUris 包含向一个URI添加id值的简便方法们.上面的小代码片段就是使用了withAppendedId() 来向UserDictionary content URI添加id