ContentProvider官方教程(3)ContentResolver查询、遍历 示例
Retrieving Data from the Provider
This section describes how to retrieve data from a provider, using the User Dictionary Provider as an example.
For the sake of clarity, the code snippets in this section call ContentResolver.query() on the "UI thread"". In actual code, however, you should do queries asynchronously on a separate thread. One way to do this is to use the CursorLoader class, which is described in more detail in the Loaders guide. Also, the lines of code are snippets only; they don't show a complete application.
To retrieve data from a provider, follow these basic steps:
- Request the read access permission for the provider.
- Define the code that sends a query to the provider.
Requesting read access permission 第1步:声明权限
To retrieve data from a provider, your application needs "read access permission" for the provider. You can't request this permission at run-time; instead, you have to specify that you need this permission in your manifest, using the <uses-permission> element and the exact permission name defined by the provider. When you specify this element in your manifest, you are in effect "requesting" this permission for your application. When users install your application, they implicitly grant this request.
要访问provier内的数据,必需先声明相应权限。
To find the exact name of the read access permission for the provider you're using, as well as the names for other access permissions used by the provider, look in the provider's documentation.
The role of permissions in accessing providers is described in more detail in the section Content Provider Permissions.
The User Dictionary Provider defines the permission android.permission.READ_USER_DICTIONARY in its manifest file, so an application that wants to read from the provider must request this permission.
Constructing the query 第2步:构造查询语句
The next step in retrieving data from a provider is to construct a query. This first snippet defines some variables for accessing 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 next snippet shows how to use ContentResolver.query(), using the User Dictionary Provider as an example. A provider client query is similar to an SQL query, and it contains a set of columns to return, a set of selection criteria, and a sort order.
The set of columns that the query should return is called a projection (the variable mProjection).
The expression that specifies the rows to retrieve is split into a selection clause and selection arguments. The selection clause is a combination of logical and Boolean expressions, column names, and values (the variable mSelectionClause). If you specify the replaceable parameter ? instead of a value, the query method retrieves the value from the selection arguments array (the variable mSelectionArgs).
使用查询语句就可以访问provider内的数据。当select语句中有?时,用对应的参数数组代替。
In the next snippet, if the user doesn't enter a word, the selection clause is set to null, and the query returns all the words in the provider. If the user enters a word, the selection clause is set to UserDictionary.Words.WORD + " = ?" and the first element of selection arguments array is set to the word the user enters.
/*
* 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[] = ""; } 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[] = 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() < ) { /*
* 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 }
This query is analogous to the SQL statement:
SELECT _ID, word, locale FROM words WHERE word = <userinput> ORDER BY word ASC;
In this SQL statement, the actual column names are used instead of contract class constants.
Protecting against malicious input
If the data managed by the content provider is in an SQL database, including external untrusted data into raw SQL statements can lead to SQL injection.
Consider this selection clause:
// Constructs a selection clause by concatenating the user's input to the column name
String mSelectionClause = "var = " + mUserInput;
If you do this, you're allowing the user to concatenate malicious SQL onto your SQL statement. For example, the user could enter "nothing; DROP TABLE *;" for mUserInput, which would result in the selection clause var = nothing; DROP TABLE *;. Since the selection clause is treated as an SQL statement, this might cause the provider to erase all of the tables in the underlying SQLite database (unless the provider is set up to catch SQL injection attempts).
To avoid this problem, use a selection clause that uses ? as a replaceable parameter and a separate array of selection arguments. When you do this, the user input is bound directly to the query rather than being interpreted as part of an SQL statement. Because it's not treated as SQL, the user input can't inject malicious SQL. Instead of using concatenation to include the user input, use this selection clause:
// Constructs a selection clause with a replaceable parameter
String mSelectionClause = "var = ?";
Set up the array of selection arguments like this:
// Defines an array to contain the selection arguments
String[] selectionArgs = {""};
Put a value in the selection arguments array like this:
// Sets the selection argument to the user's input
selectionArgs[] = mUserInput;
A selection clause that uses ? as a replaceable parameter and an array of selection arguments array are preferred way to specify a selection, even if the provider isn't based on an SQL database.
Displaying query results 第3步:处理返回的结果
The ContentResolver.query() client method always returns a Cursor containing the columns specified by the query's projection for the rows that match the query's selection criteria. A Cursor object provides random read access to the rows and columns it contains. Using Cursor methods, you can iterate over the rows in the results, determine the data type of each column, get the data out of a column, and examine other properties of the results. Some Cursor implementations automatically update the object when the provider's data changes, or trigger methods in an observer object when the Cursor changes, or both.
查询返回的结果用Cursor指向。
Note: A provider may restrict access to columns based on the nature of the object making the query. For example, the Contacts Provider restricts access for some columns to sync adapters, so it won't return them to an activity or service.
If no rows match the selection criteria, the provider returns a Cursor object for which Cursor.getCount() is 0 (an empty cursor).
If an internal error occurs, the results of the query depend on the particular provider. It may choose to return null, or it may throw an Exception.
Since a Cursor is a "list" of rows, a good way to display the contents of a Cursor is to link it to a ListView via a SimpleCursorAdapter.
SimpleCursorAdapter系统写的与Cursor和ListView相关的适配器。
The following snippet continues the code from the previous snippet. It creates a SimpleCursorAdapter object containing the Cursor retrieved by the query, and sets this object to be the adapter for a ListView:
// Defines a list of columns to retrieve from the Cursor and load into an output row
String[] mWordListColumns =
{
UserDictionary.Words.WORD, // Contract class constant containing the word column name
UserDictionary.Words.LOCALE // Contract class constant containing the locale column name
}; // Defines a list of View IDs that will receive the Cursor columns for each row
int[] mWordListItems = { R.id.dictWord, R.id.locale}; // Creates a new SimpleCursorAdapter
mCursorAdapter = new SimpleCursorAdapter(
getApplicationContext(), // The application's Context object
R.layout.wordlistrow, // A layout in XML for one row in the ListView
mCursor, // The result from the query
mWordListColumns, // A string array of column names in the cursor
mWordListItems, // An integer array of view IDs in the row layout
); // Flags (usually none are needed) // Sets the adapter for the ListView
mWordList.setAdapter(mCursorAdapter);
Note: To back a ListView with a Cursor, the cursor must contain a column named _ID. Because of this, the query shown previously retrieves the _ID column for the "words" table, even though the ListView doesn't display it. This restriction also explains why most providers have a _ID column for each of their tables.
为了能在ListView中显示查询结果,在查询时必需指定_ID字段。
Getting data from query results 第4步:可以遍历查询结果,查具体字段内容。
Rather than simply displaying query results, you can use them for other tasks. For example, you can retrieve spellings from the user dictionary and then look them up in other providers. To do this, you iterate over the rows in the Cursor:
// Determine the column index of the column named "word"
int index = mCursor.getColumnIndex(UserDictionary.Words.WORD); /*
* Only executes if the cursor is valid. The User Dictionary Provider returns null if
* an internal error occurs. Other providers may throw an Exception instead of returning null.
*/ if (mCursor != null) {
/*
* Moves to the next row in the cursor. Before the first movement in the cursor, the
* "row pointer" is -1, and if you try to retrieve data at that position you will get an
* exception.
*/
while (mCursor.moveToNext()) { // Gets the value from the column.
newWord = mCursor.getString(index); // Insert code here to process the retrieved word. ... // end of while loop
}
} else { // Insert code here to report an error if the cursor is null or the provider threw an exception.
}
Cursor implementations contain several "get" methods for retrieving different types of data from the object. For example, the previous snippet uses getString(). They also have a getType() method that returns a value indicating the data type of the column.
Cursor提供了很多 查具体字段内容的函数。
ContentProvider官方教程(3)ContentResolver查询、遍历 示例的更多相关文章
- ContentProvider官方教程(5)ContentResolver插入、更新、删除 示例
Inserting, Updating, and Deleting Data In the same way that you retrieve data from a provider, you a ...
- ContentProvider官方教程(4)ContentResolver权限
Content Provider Permissions A provider's application can specify permissions that other application ...
- ContentProvider官方教程(9)定义一个provider完整示例:实现方法,定义权限等
Creating a Content Provider In this document Designing Data Storage Designing Content URIs Implement ...
- ContentProvider官方教程(7)3种访问形式:批处理、异步访问、intent间接访问(临时URI权限)
Alternative Forms of Provider Access Three alternative forms of provider access are important in app ...
- ContentProvider官方教程(2)简介、Content URIs
In this document Overview Accessing a provider Content URIs Content Provider Basics A content provid ...
- ContentProvider官方教程(1)何时用content provider
Content Providers Content providers manage access to a structured set of data. They encapsulate the ...
- BeatSaber节奏光剑插件开发官方教程2-简单的插件示例
原文:https://wiki.assistant.moe/modding/example-mod 一.在开始之前 1 确保你已经看过教你如何添加插件模板的教程,且你已经使用插件模板创建了一个新项目 ...
- ContentProvider官方教程(10)<provider>元素及属性介绍
The <provider> Element Like Activity and Service components, a subclass of ContentProvider mus ...
- ContentProvider官方教程(6)provider支持的数据类型
Provider Data Types Content providers can offer many different data types. The User Dictionary Provi ...
随机推荐
- override 与 overdown 的区别
重写与重载的区别 1. 重载是方法的名称相同.参数或参数类型不同,进行多次重载以适应不同的需要 2. 重写是进行基类中函数的重写.为了适应需要.
- Codeforces Beta Round #93 (Div. 1 Only) D. Fibonacci Sums
先考虑一个斐波那契数能分成其他斐波那契数的方案,假如f[i]表示第i个斐波那契数,那么只要对他进行拆分,f[i-1]这个数字必定会存在.知道这一点就可以进行递推了.先将数字分成最少项的斐波那契数之和, ...
- ios pyudaren
ed2k://|file|%E9%A1%B9%E7%9B%AE%E6%8D%95%E9%B1%BC%E8%BE%BE%E4%BA%BA01.rmvb|67044010|9e013987298d7900 ...
- Android中使用ShareSDK实现分享
1,在http://www.mob.com官网上去创建一个后台应用(如果没有账号的同学要去先注册一下),主要后去的是你新创建的应用的appKey值 2,这里我们分享新浪微博为例,在新浪微博的sdk中创 ...
- CSS3 Transform Matrix
css3中的transform让我们操作变形变得很简单,诸如,translate–移动,scale–缩放,rotate–旋转,skew–斜切.这几个属性很方便,也很简单,但是其中matrix我们就不常 ...
- JSTL标签,EL表达式,OGNL表达式,struts2标签 汇总
一下纯属个人总结摘抄,总结一起方便查看,解决疑问,有遗漏或错误,还请指出. 1,JSTL标签总结: a).JSTL标签有什么用? JSTL是由JCP(Java Commu ...
- 本周PSP+历年作品评论
本周PSP 类别 内容 开始时间 结束时间 间断时间 净时间(min) 9月11号 看书 构建之法 19:00 21:00 14 106 9月12号 写程序 词频统计多需求版 8:00 14:23 3 ...
- windows中的上帝模式开启方法
在任何地方创建一个新的文件夹 把文件夹命名为"GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}" 回车,ok了
- Entity Framework 无法对没有主键的视图映射实体的解决办法
我们在使用Entity Framework的时候经常会把数据库中的某一个视图映射为EF的实体,但是如果数据库视图中的列没有包含表的主键列,EF会报出警告说视图没有主键,导致视图映射为实体失败,错误如下 ...
- SVN使用(一)
SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很多不同的版本,这就需要程序员有效的管理代码,在需要的时候可以迅速,准确取出相应的版本. Subversion是什么? ...