【问题标题】:What are the semantics of withValueBackReference?withValueBackReference 的语义是什么?
【发布时间】:2011-01-11 07:44:13
【问题描述】:

我无法弄清楚withValueBackReference 的确切语义。

我已经阅读了使用此方法的示例代码(例如添加新联系人的代码),提供的 backReference 值为 0。这是什么意思?

文档说:

来自后面引用的列值优先于 withValues(ContentValues) 中指定的值

【问题讨论】:

  • 我在 SO 上找到了这个讨论 - 它讨论了在目标是在单个操作中保存 主记录和详细记录的情况下使用 withValueBackReference 方法。但是,我还是不明白这里的0数字后面的参考值是怎么回事! stackoverflow.com/questions/3224857/…

标签: android android-contentprovider


【解决方案1】:

这个问题与内容提供商的批处理操作有关。示例修改自this related question

在创建一批操作时,首先创建一个要执行的操作列表:

ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

然后使用 applyBatch 方法将它们应用到内容提供者。

ContentProviderResult[] results = this.getContentResolver().applyBatch(FooBar.AUTHORITY, operations);

这是基本概念,所以让我们应用它。假设我们有一个内容提供者,它处理 Foo 记录的 uris 和一些称为 Bar 的子记录。

content://com.stackoverflow.foobar/foo

content://com.stackoverflow.foobar/foo/#/bar

现在我们只插入 2 个新的 Foo 记录,分别称为“Foo A”和“Foo B”,示例如下。

ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

//add a new ContentProviderOperation - inserting a FOO record with a name and a decscription
operations.add(ContentProviderOperation.newInsert(intent.getData())
    .withValue(FOO.NAME, "Foo A")
    .withValue(FOO.DESCRIPTION, "A foo of impeccable nature")
    .build());

//let's add another
operations.add(ContentProviderOperation.newInsert(intent.getData())
    .withValue(FOO.NAME, "Foo B")
    .withValue(FOO.DESCRIPTION, "A foo of despicable nature")
    .build());

ContentProviderResult[] results = this.getContentResolver().applyBatch(FooBar.AUTHORITY, operations);

这里没什么特别的,我们将 2 个 ContentProviderOperation 项添加到我们的列表中,然后将列表应用到我们的内容提供者。 results 数组中填充了我们刚刚插入的新记录的 id。

假设我们想做一些类似的事情,但我们也想在一个批处理操作中将一些子记录添加到我们的内容提供者中。我们想将子记录附加到我们刚刚创建的 Foo 记录中。问题是我们不知道父 Foo 记录的 id,因为批处理尚未运行。这就是 withValueBackReference 帮助我们的地方。我们来看一个例子:

ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

//add a new ContentProviderOperation - inserting a Foo record with a name and a decscription
operations.add(ContentProviderOperation.newInsert(intent.getData())
    .withValue(FOO.NAME, "Foo A")
    .withValue(FOO.DESCRIPTION, "Foo of impeccable nature")
    .build());

//let's add another
operations.add(ContentProviderOperation.newInsert(intent.getData())
    .withValue(FOO.NAME, "Foo B")
    .withValue(FOO.DESCRIPTION, "Foo of despicable nature")
    .build());

//now add a Bar record called [Barbarella] and relate it to [Foo A]
operations.add(ContentProviderOperation.newInsert(intent.getData()
    .buildUpon()
    .appendPath("#") /* We don't know this yet */
    .appendPath("bar")
    .build())
.withValueBackReference (BAR.FOO_ID, 0) /* Index is 0 because Foo A is the first operation in the array*/
.withValue(BAR.NAME, "Barbarella")
.withValue(BAR.GENDER, "female")
.build());

//add a Bar record called [Barbarian] and relate it to [Foo B]
operations.add(ContentProviderOperation.newInsert(intent.getData()
    .buildUpon()
    .appendPath("#") /* We don't know this yet */
    .appendPath("bar")
    .build())
.withValueBackReference (BAR.FOO_ID, 1) /* Index of parent Foo B is 1*/
.withValue(BAR.NAME, "Barbarian")
.withValue(BAR.GENDER, "male")
.build());

ContentProviderResult[] results = this.getContentResolver().applyBatch(FooBar.AUTHORITY, operations);

因此 withValueBackReference() 方法允许我们在知道要关联的父项的 id 之前插入相关记录。反向引用索引只是将返回我们要查找的 id 的操作的索引。根据您希望包含 id 的结果来考虑它可能更容易。例如,results[1] 将包含“Foo B”的 id,因此我们用来反向引用“Foo B”的索引是 1。

【讨论】:

  • 这是一个无可挑剔的解释。万分感谢!我多么希望我能多次投票。
  • 这是黄金,是我见过的对反向引用的唯一体面解释之一。已在我的应用中实现 - 谢谢
  • 有史以来最好的答案,非常感谢,最好有一个只能输入 5 条回复的星旗 :) 你肯定拥有一个!
  • 你确定用主记录的ID替换#登录content://com.stackoverflow.foobar/foo/#/bar真的有效吗?我试过了,似乎没有。如果我查看source of ContentProviderOperation,似乎反向引用仅适用于ContentValues,而不是URI。
  • 很好的解释,让我意识到一个功能为我节省了数小时的痛苦。非常感谢。
猜你喜欢
  • 2014-05-22
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
相关资源
最近更新 更多