Content Providers是用来管理结构化数据集进行访问的一组接口。它们对数据进行封装,并提供了定义数据安全的机制。Content
Providers是进程间数据访问的标准接口。
当要使用content provider访问数据时,我们需要在应用程序的Context中使用ContentResolver对象作为客户端,同provider进行
通信。content provider接收来自客户端的数据请求,执行请求动作,并返回结果。
Content Providers基础
Content provider管理对于中央数据库的访问。Provider提供与数据进行交互的接口。其他应用程序可以使用provider客户端对象
(ContentResolver)访问Content provider。providers和provider客户端共同提供了一个一致的标准数据接口用来处理进程间通信和安全的数据访问。
一、概述
Content provider以类似于关系数据库中一个或多个表的方式给外部的应用程序提供数据。表中一行代表provider所收集的所有数
据类型的一个实例,一列中的每一行代表数据中某个类型的一个实例。
二、访问Content provider
应用程序使用ContentResolver客户端对象来访问content provider的数据。ContentResolver对象与Content provider的一个具体
子类的实例拥有相同名字的方法,当ContentResolver对象执行某个方法时,就会调用Content provider实例中相同名字的方法。
ContentResolver对象的方法提供了基本的‘CRUD’(create创建,retrieve检索,update更新和delete删除)数据存储的功能。
示例:
// Queries the user dictionary and returns results mCursor = getContentResolver().query( UserDictionary.Words.CONTENT_URI, // 词表的内容URI mProjection, // 每行中返回数据的列的名称, // null表示返回所有列的数据。 mSelectionClause // 过滤条件 mSelectionArgs, // 过滤条件的参数 mSortOrder); // 返回行的排序方式
query(Uri,projection,selection,selectionArgs,sortOrder)
的参数同SQL SELECT语句之间的对应关系:
query()参数 | SELECT关键字/参数 | 注解 |
Uri | FROM table_name | Uri相当于表名 |
projection | col,col,col | projection是一个存放列名的数组,它规定了查询结果中应当包含哪些列 |
selection | WHERE col= |
selection 指定了检索行的条件 |
selectionArgs | (No exact equivalent. Selection arguments replace ? placeholders in the selection clause.) |
|
sortOrder | ORDER BY col,col,... | 排序方式 |
1、Content URIs
Content URI是provider中用来标识数据的URI。Content URI包括整个provider的符号名称(authority)和表的路径名(path)。
当调用客户端的方法来访问provider中的一个表时,这个表的Content URI会作为这个方法一个参数。
ContentResolver客户端对象解析出URI的authority,用authority与系统已知的provider的表的authority比较,来解析出对应的
provider。然后, ContentResolver客户端对象将在查询参数传递给正确的provider。
Content provider使用Content URI的path来选择正确的表进行访问。
例如“words”的URI如下:
content://user_dictionary/words
其中use_dictionary是provider的authority;words是provider的path;content://是provider的scheme,用来标识这是一个
Content URI。
许多providers允许你通过在URI的结尾处追加一个ID值访问一个表中一行。例如,从用户词典中检索_ID为4的那行数据,可以使用如下的内容URI:
Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
当我们检索多行数据,并希望更新或者删除其中一行时,我们经常会使用id这个值。
二、从provider中检索数据
这个部分描述如何检索数据。我们使用用户词典Provider(the User Dictionary Provider)来举例说明。
注意:为了方便起见,下面的代码会在UI线程中调用ContentResolver.query()
,但是在实际的代码中,我们应当在一个独立的线程中
异步进行查询操作。一种方法是:使用CursorLoader
类。
为了从provider中检索数据,请遵循以下的基本步骤:
a、获得provider的读访问权限
b、定义发送查询命令给provider的代码
1、获取provider的读访问权限
为了从provider中查询数据,应用程序必须有此provider的读访问权限。你必须在mainfest文件中指定权限,本例中使用如下语句
获取权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" ></uses-permission>
程序的第一部分是定义了访问the User Dictionary Provider的一些变量。
// A "projection" defines the columns that will be returned for each row String[] mProjection = { UserDictionary.Words._ID, // Contract class constant for the _ID column name UserDictionary.Words.WORD, // Contract class constant for the word column name UserDictionary.Words.LOCALE // Contract class constant for the locale column name }; // Defines a string to contain the selection clause String mSelectionClause = null; // Initializes an array to contain selection arguments String[] mSelectionArgs = {""};接下来的程序以 the User Dictionary Provider为例,显示如何使用
ContentResolver.query()
。Provider客户端查询类似于SQL查询,它包含一组返回的列值,一组查询条件和排序规则。
查询返回的列的集合被称作一个Projection。
检索指定行的条件表达式被分成selection语句(a selection clause)和selection参数(selection arguments)。selection语句是
由逻辑和布尔表达式,列名和值组成。如果你指定的是可替换参数?代替一个值,那么查询方法将从selection参数中检索数据。
下面的代码中,如果用户没有输入任何单词,selection语句被设置成null,查询会返回provider中所有的单词。如果用户输入一
个单词,查询语句被设置成UserDictionary.Words.Word + " = ?",同时selection参数数组中的第一个元素被设置成用户输入的单词。
/* * This defines a one-element String array to contain the selection argument. */ String[] mSelectionArgs = {""}; // Gets a word from the UI mSearchString = mSearchWord.getText().toString(); // Remember to insert code here to check for invalid or malicious input. // If the word is the empty string, gets everything if (TextUtils.isEmpty(mSearchString)) { // Setting the selection clause to null will return all words mSelectionClause = null; mSelectionArgs[0] = ""; } else { // Constructs a selection clause that matches the word that the user entered. mSelectionClause = UserDictionary.Words.WORD + " = ?"; // Moves the user's input string to the selection arguments. mSelectionArgs[0] = mSearchString; } // Does a query against the table and returns a Cursor object mCursor = getContentResolver().query( UserDictionary.Words.CONTENT_URI, // The content URI of the words table mProjection, // The columns to return for each row mSelectionClause // Either null, or the word the user entered mSelectionArgs, // Either empty, or the string the user entered mSortOrder); // The sort order for the returned rows // Some providers return null if an error occurs, others throw an exception if (null == mCursor) { /* * Insert code here to handle the error. Be sure not to use the cursor! You may want to * call android.util.Log.e() to log this error. * */ // If the Cursor is empty, the provider found no matches } else if (mCursor.getCount() < 1) { /* * Insert code here to notify the user that the search was unsuccessful. This isn't necessarily * an error. You may want to offer the user the option to insert a new row, or re-type the * search term. */ } else { // Insert code here to do something with the results }