Android - 如何将与两个表相关的数据传递给内容提供者的插入方法
Posted
技术标签:
【中文标题】Android - 如何将与两个表相关的数据传递给内容提供者的插入方法【英文标题】:Android - How can I pass data related to two tables to a the insert method of a Content Provider 【发布时间】:2015-01-31 04:07:09 【问题描述】:我需要插入与Order
及其对应的Detail
相关的数据。
如果没有ContentProvider
,我会这样做:
public boolean insertOrder(Order order, ArrayList<OrderDetail> items)
boolean wasSuccessful = false;
ContentValues cvOrder = new ContentValues();
cvPedido.put(ORDER_CUSTOMER_ID, order.getCustomerId());
cvPedido.put(ORDER_CUSTOMER_NAME, order.getCustomerName());
String insertQuery = "INSERT INTO " + ORDER_DETAIL_TABLE
+ " VALUES (?,?)";
//...
try
this.openWriteableDB();
SQLiteStatement statement = db.compileStatement(insertQuery);
db.beginTransaction();
long idOrder = db.insertOrThrow(ORDER_TABLE, null, cvOrder);
if (idOrder > 0)
for (int i = 0; i < items.size(); i++)
OrderDetail detail=items.get(i);
statement.clearBindings();
statement.bindString(1, detail.getDescription);
statement.bindDouble(2, detail.getPrice);
//...
statement.execute();
db.setTransactionSuccessful();
wasSuccessful = true;
finally
db.endTransaction();
this.closeDB();
return wasSuccessful;
问题是现在我想使用ContentProvider
,但我不知道如何处理这种情况,即必须将有关两个或多个表的数据传递给单个 CRUD 操作,知道 @ 987654326@操作只接受两个参数:
@Override
public Uri insert(Uri uri, ContentValues values)
当您必须在事务中插入关系数据时,您在 ContentProvider 中做什么?
提前致谢。
【问题讨论】:
【参考方案1】:您应该使用ContentProviderOperation。由于它是您的ContentProvider
,您可以确保applyBatch()
将执行事务中的所有操作。所有标准的内容提供者也确保是这种情况。
请参阅我的博客 post about ContentProviderOperation 和我关于 how to use withBackReference() to access results of previous operations 的其他帖子 - 您需要访问 orderId
。
一个重要的警告:一批中的所有ContentProviderOperations
必须使用相同的权限 - 但可以使用不同的 URI!在你的情况下应该没问题。
【讨论】:
对不起,我之前没有将此标记为答案,但由于我必须回到一个 ios 项目,然后出现其他事情,直到昨天我才能回到我的android 项目并确认您的解决方案是正确的答案。 没问题。感谢您牢记这一点并在这么长时间后支持我!这本身就值得获得 SO 奖。 你真的应得的,因为你让我走上了正轨。再次非常感谢您,很抱歉,如果我花了这么多时间将其标记为答案,但由于我在空闲时间学习 Android,我不得不推迟这个个人项目一段时间。最后,如果有人发现它有用,这里有一个示例,说明如何在Content Provider
github.com/google/iosched/blob/master/android/src/main/java/com/… 中实现 applyBatch
方法【参考方案2】:
您可以将所有数据放入 ContentValues 并拥有一个提供者。您必须对订单详细信息进行一些创意。
在伪代码下面,我用一个整数然后是项目动态创建了一个键“DETAIL”。
ContentValues values = new ContentValues();
values.put(ORDER_ID,orderid);
for (int i = 0; i < items.size(); i++)
values.put("DETAIL" + Integer.ToString(i),items.get(i));
Uri uri = context.getContentResolver().insert(
ORDER_URI, values);
然后在内容提供者中进行整理。
@Override
public Uri insert(Uri uri, ContentValues values)
int uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = database.getWritableDatabase();
long id = 0;
switch (uriType)
case ORDER:
// trim name and description
trimNameDescriptions(values);
try
id = sqlDB.insertOrThrow(ORDERS_TABLE,
null, values);
Integer i =0;
do (values.containsKey("DETAIL" + i.toString())
ContentValues v = new ContentValues();
v.put("DETAIL",values.get("Detail" + i.toString()));
v.put("ORDERID",id);
//ACTUALLY CALL THE INSERT METHOD OF THE PROVIDER
insert(DETAIL_URI,v);
i+=1;
【讨论】:
所以不需要交易? 好吧,您可以再对其进行一些调整,然后在其中放置一笔交易。我只是展示了如何使用 ContentValues 来传递信息。如果我是您,我会使用您问题中的代码或修改订单,以便将其写入 ContentValues。 谢谢@danny117。所以 ContentProviders 基本上只能同时使用一张表? Idk 值得一试。我有一个视图,我严格查询提供程序中的数据,该视图使它看起来像表查询的代码,因此它更具结构化。如果有什么让代码看起来很漂亮的话。 @eddy:不。您可以在一个批次中处理多个表而不会出现问题。你就是不能越权。【参考方案3】:您可以设计内容提供程序来镜像您的 SQLite 表,并使用与上述相同的 insertOrder
代码。
只需为每个表(uri)使用 insert
的内容提供者,即可执行与 insertOrder
方法中类似的操作
另一种选择是定义您的内容提供者 URI 以结合您的 Order
和 items
,并在提交到底层数据模型之前在内容提供者中自己实现解析。
【讨论】:
你能举个例子吗? 对不起,我也不明白你的想法 我认为这个想法是为这种情况使用一个特殊的 URI,例如content://authority/orderwithdetails/orderId
。问题是:这在这种情况下不起作用,因为要插入许多细节而不仅仅是一个。以上是关于Android - 如何将与两个表相关的数据传递给内容提供者的插入方法的主要内容,如果未能解决你的问题,请参考以下文章
如何将片段中的 ListView 对象的数据传递给 Activity?
如何将计时器中的数据传递给新的 ViewController (Swift 3)
jQuery 将 Ajax 调用中的数据传递给 MVC 操作方法
如何将表单 FormSeetController 中的数据传递给 ViewController?
如何通过 PageViewController 将 viewController 的数据传递给 pageViewController 的第二个 ViewController