Этот вопрос относится к пакетной операции с поставщиком контента. Пример изменен с на этот связанный вопрос .
При создании пакета операций сначала создайте список операций, которые нужно выполнить, используя:
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
затем примените их к поставщику контента, используя метод applyBatch.
ContentProviderResult[] results = this.getContentResolver().applyBatch(FooBar.AUTHORITY, operations);
Это базовая концепция, поэтому давайте ее применим. Предположим, у нас есть поставщик контента, который обрабатывает uris для записей Foo и некоторых дочерних записей, называемых Bar.
Содержание: //com.stackoverflow.foobar/foo
содержание: //com.stackoverflow.foobar/foo/#/bar
А пока мы просто вставим две новые записи 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 в наш список, а затем применяем этот список к нашему поставщику контента. Массив результатов заполнен идентификаторами новых записей, которые мы только что вставили.
Допустим, мы хотели сделать что-то подобное, но мы также хотим добавить несколько дочерних записей в наш контент-провайдер за одну пакетную операцию. Мы хотим прикрепить дочерние записи к только что созданным записям Foo. Проблема в том, что мы не знаем идентификатор родительских записей Foo, потому что пакет не был запущен. Именно здесь нам помогает 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 () позволяет нам вставлять связанные записи, прежде чем мы узнаем идентификатор родителя, с которым мы хотим связать их. Индекс обратной ссылки - это просто индекс операции, которая возвращает идентификатор, который мы хотим найти. Возможно, проще думать об этом с точки зрения того, какой результат вы ожидаете содержать идентификатор. например, results[1]
будет содержать идентификатор для "Foo B", поэтому индекс, который мы используем для обратной ссылки на "Foo B", равен 1.