Android 如何通过 CursorLoader 使用 ContentProvider 的 insert() 方法将值正确插入 SQLite 数据库?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11131058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to properly insert values into the SQLite database using ContentProvider's insert() method through a CursorLoader?
提问by Andy
I was reading the doc, but I am still not too sure. Its says to use getContentResolver()
, but then that really isn't using CursorLoader. So is there a way to do it through CursorLoader
? I know how to do it with query()
. Are the steps very similar? Even just a link that explains exactly this would be helpful.
我正在阅读文档,但我仍然不太确定。它说要使用getContentResolver()
,但那真的不是在使用 CursorLoader。那么有没有办法做到这一点CursorLoader
?我知道如何使用query()
. 步骤非常相似吗?即使只是一个准确解释这一点的链接也会有所帮助。
Please note, do not link me to the Google doc as they do not have an example that ever uses the insert()
method from ContentProvider using a CursorLoader
.
请注意,不要将我链接到 Google 文档,因为他们没有使用insert()
ContentProvider 使用CursorLoader
.
Thanks in advance!!
提前致谢!!
Edit: I should probably mention the reason I am confused with this is because calling a new CursorLoader
automatically calls ContentProviders
query()
method. But how can I do the same for insert?
编辑:我可能应该提到我对此感到困惑的原因是因为调用新的CursorLoader
自动调用ContentProviders
query()
方法。但是我怎么能对插入做同样的事情呢?
回答by Alex Lockwood
Check out my blog poston the subject:
查看我关于该主题的博客文章:
Content Resolvers and Content Providers
内容解析器和内容提供者
The CursorLoader
has nothing to do with it.
该CursorLoader
有什么用它做。
Insertion is a totally different concept... it has absolutely nothingto do with the CursorLoader
. When coupled with the LoaderManager
, the CursorLoader
automatically queries your database and updates itself when the ContentObserver
is notified of a datastore change. It has nothing to do with the actual process of inserting data into your database.
插入是一个完全不同的概念...它绝对没有做的CursorLoader
。与 结合使用时LoaderManager
, 会CursorLoader
自动查询您的数据库并在ContentObserver
收到数据存储更改通知时自行更新。它与将数据插入数据库的实际过程无关。
How requests to the ContentResolver
are resolved
如何ContentResolver
解决对 的请求
When you insert (or query or update or delete) data into your database via the content provider, you don't communicate with the provider directly. Instead, you use the ContentResolver
object to communicate with the provider (note that the ContentResolver
is a private instance variable in your application's global Context
) . More specifically, the sequence of steps performed is:
当您通过内容提供者将数据插入(或查询、更新或删除)数据库时,您不会直接与提供者通信。相反,您使用该ContentResolver
对象与提供者进行通信(请注意,ContentResolver
是您应用程序的 global 中的私有实例变量Context
)。更具体地说,执行的步骤顺序是:
You call
getContentResolver().insert(Uri, ContentValues);
The
ContentResolver
object determines the authority of the Uri.The
ContentResolver
relays the request to the content provider registered with the authority (this is why you need to specify the authority in theAndroidManifest.xml
).The content provider receives the request and performs the specified operation (in this case
insert
). How and where the data is inserted depends on how you implemented theinsert
method (ContentProvider
is an abstract class that requires the user to implementinsert
,query
,delete
,update
, andgetType
).
你打电话
getContentResolver().insert(Uri, ContentValues);
的
ContentResolver
对象确定URI的权限。将
ContentResolver
请求中继到向授权注册的内容提供者(这就是您需要在 中指定授权的原因AndroidManifest.xml
)。内容提供者接收请求并执行指定的操作(在本例中为
insert
)。如何以及在哪里被插入的数据取决于你如何实现的insert
方法(ContentProvider
是需要用户的抽象类来实现insert
,query
,delete
,update
,和getType
)。
Hopefully you were able to wrap your head around that at least a little. The reason why there are so many steps involved is because Android (1) allows applications to have more than one content provider, and (2) needs to ensure that apps can securely share data with other third-party apps. (It wasn't because it wanted to confuse you, I promise).
希望您能够至少稍微了解一下。之所以涉及这么多步骤,是因为 Android (1) 允许应用程序拥有多个内容提供者,以及 (2) 需要确保应用程序可以安全地与其他第三方应用程序共享数据。(这不是因为它想迷惑你,我保证)。
Inserting data via the ContentProvider
通过插入数据 ContentProvider
Now that you (hopefully) have a better idea of how the ContentResolver
is able to relay these requests to the content provider, inserting the data is fairly straight forward:
现在您(希望)对如何将ContentResolver
这些请求中继到内容提供者有了更好的了解,插入数据是相当简单的:
First, decide which uri you want to have matched by your content provider. This depends on how you decided to match your uris with the
UriMatcher
. Each uri you have represents a different means of inserting data into your internal database (i.e. if your app has two tables, you will probably have two uris, one for each table).Create a new
ContentValues
object and use it to package the data you wish to send to the content provider. TheContentValues
object maps column names to data values. In the below example, the column name is "column_1" and the value being inserted under that column is "value_1":ContentValues values = new ContentValues(); values.put("column_1", "value_1");
Once received, the content provider will (in your case) pass the
values
object to yourSQLiteDatabase
(via theSQLiteDatabase.insert(String table, String nullColumnHack, ContentValues values)
method). Unlike theContentProvider
, this method is implemented for you... theSQLiteDatabase
knows how to handle thevalues
object and will insert the row into the database, returning the row id of the inserted row, or-1
if the insertion failed.
首先,确定您希望与您的内容提供商匹配的 uri。这取决于您如何决定将 uri 与
UriMatcher
. 您拥有的每个 uri 代表将数据插入内部数据库的不同方式(即,如果您的应用程序有两个表,您可能会有两个 uri,每个表一个)。创建一个新
ContentValues
对象并使用它来打包您希望发送给内容提供者的数据。该ContentValues
对象将列名映射到数据值。在下面的示例中,列名称是“column_1”,该列下插入的值是“value_1”:ContentValues values = new ContentValues(); values.put("column_1", "value_1");
收到后,内容提供者将(在您的情况下)将
values
对象传递给您SQLiteDatabase
(通过SQLiteDatabase.insert(String table, String nullColumnHack, ContentValues values)
方法)。与 不同ContentProvider
,此方法是为您实现的...SQLiteDatabase
知道如何处理values
对象并将行插入数据库,返回插入行的行 ID,或者-1
如果插入失败。
... and that's how you insert data into your database.
...这就是您将数据插入数据库的方式。
TL;DR
TL; 博士
Use getContentResolver().insert(Uri, ContentValues);
用 getContentResolver().insert(Uri, ContentValues);
回答by davidcesarino
Convert Cursor to ContentValues for easy database insertion.
将 Cursor 转换为 ContentValues 以便于数据库插入。
Its says to use getContentResolver(), but then that really isn't using CursorLoader
它说要使用 getContentResolver(),但那真的不是使用 CursorLoader
Besides what Alex said, there's nothing preventing you from iterating through the Cursor
returned, putting them into ContentValue
s and then inserting that (say, to a different DB).
除了亚历克斯所说的之外,没有什么可以阻止您遍历Cursor
返回的内容,将它们放入ContentValue
s 然后插入(例如,插入不同的数据库)。
Just an example from the top of my head (a simple Cursor
of two String
columns):
只是我头脑中的一个例子(简单Cursor
的两String
列):
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (cursor.moveToFirst()) {
ArrayList<ContentValues> values = new ArrayList<ContentValues>();
do {
ContentValues row = new ContentValues();
DatabaseUtils.cursorStringToContentValues(cursor, fieldFirstName, row);
DatabaseUtils.cursorStringToContentValues(cursor, fieldLastName, row);
values.add(row);
} while (cursor.moveToNext());
ContentValues[] cv = new ContentValues[values.size()];
values.toArray(cv);
getContentResolver().bulkInsert(CONTENT_NAMES, cv);
}
}
There are probably more efficient ways to do that (and definitely some integrity checks), but that was my first thought...
可能有更有效的方法来做到这一点(当然还有一些完整性检查),但这是我的第一个想法......