Как правильно вставить значения в базу данных SQLite с помощью метода contentProvider insert() через CursorLoader?

Я читал документ, но я все еще не слишком уверен. Он говорит использовать getContentResolver(), но тогда это действительно не использует CursorLoader. Итак, есть ли способ сделать это через CursorLoader? Я знаю, как это сделать с помощью query(). Являются ли шаги очень похожими? Даже просто ссылка, которая объясняет именно это, будет полезна.

Обратите внимание: не связывайте меня с документом Google, так как у них нет примера, который когда-либо использовал метод insert() из ContentProvider с помощью CursorLoader.

Спасибо заранее!

Изменить: я должен, вероятно, упомянуть причину, с которой я смущен, потому что вызов нового CursorLoader автоматически вызывает метод ContentProviders query(). Но как я могу сделать то же самое для вставки?

Ответ 1

Отправляйте сообщение в блоге по теме:

Content Resolvers и поставщики контента


CursorLoader не имеет к этому отношения.

Вставка - совершенно другое понятие... она не имеет абсолютно никакого отношения к CursorLoader. В сочетании с LoaderManager, CursorLoader автоматически запрашивает вашу базу данных и обновляет себя, когда ContentObserver уведомляется об изменении хранилища данных. Это не имеет никакого отношения к фактическому процессу вставки данных в вашу базу данных.

Как разрешаются запросы к ContentResolver

Когда вы вставляете (или запрашиваете или обновляете или удаляете) данные в свою базу данных через поставщика контента, вы напрямую не общаетесь с провайдером. Вместо этого вы используете объект ContentResolver для связи с провайдером (обратите внимание, что ContentResolver является частной переменной экземпляра в приложении global Context). Более конкретно, последовательность выполненных шагов:

  • Вы вызываете getContentResolver().insert(Uri, ContentValues);

  • Объект ContentResolver определяет полномочия Uri.

  • ContentResolver передает запрос поставщику контента, зарегистрированному в полномочном органе (поэтому вам нужно указать полномочия в AndroidManifest.xml).

  • Поставщик контента получает запрос и выполняет указанную операцию (в данном случае insert). Как и где данные вставляются, зависит от того, как вы реализовали метод insert (ContentProvider - абстрактный класс, который требует, чтобы пользователь реализовал insert, query, delete, update и getType).

Надеюсь, вы могли хоть немного обернуть вокруг себя. Причина, по которой происходит так много шагов, заключается в том, что Android (1) позволяет приложениям иметь более одного поставщика контента, и (2) должен гарантировать, что приложения могут безопасно обмениваться данными с другими сторонними приложениями. (Это было не потому, что он хотел смутить вас, я обещаю).

Вставка данных через ContentProvider

Теперь, когда вы (надеюсь) лучше поймете, как ContentResolver сможет передать эти запросы поставщику контента, вставка данных достаточно проста:

  • Сначала определите, какой uri вы хотите согласовать с вашим поставщиком контента. Это зависит от того, как вы решили совместить свой урис с UriMatcher. Каждый uri, который у вас есть, представляет собой другое средство вставки данных во внутреннюю базу данных (т.е. Если ваше приложение имеет две таблицы, у вас, вероятно, будет два uris, по одному для каждой таблицы).

  • Создайте новый объект 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 и вставляет строку в базу данных, возвращая идентификатор строки вставленной строки или -1 если вставка не удалась.

... и то, как вы вставляете данные в свою базу данных.


TL; DR

Используйте getContentResolver().insert(Uri, ContentValues);

Ответ 2

Преобразование курсора в ContentValues ​​для удобной вставки базы данных.

В нем говорится использовать getContentResolver(), но тогда это действительно не использует CursorLoader

Кроме того, что сказал Алекс, ничто не мешает вам повторять через Cursor, возвращаясь, помещая их в ContentValue, а затем вставляя их (скажем, в другую БД).

Просто пример из верхней части моей головы (простой 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);
    }
}

Есть, вероятно, более эффективные способы сделать это (и, безусловно, некоторые проверки целостности), но это была моя первая мысль...