正文  数据库 > Content Provider >

android Content Provider详解一

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

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客户端对象来操作provider.providers 和provider客户端一起提供了一致的,标准的接口来操作用于进程间通讯的数据并保处数据的安全性.

本节讲解以下基础知识:

· content providers如何工作.

· 从content provider取得数据的API.

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

· 其它有助于使用providers的API.

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

举个例子,Android平台中的一个内建的provider是用户词典,它存储了用户想保存的非标准词的拼写.表1 演示了数据在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:www.2cto.com

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

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

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

 


作者:nkmnkm