Intereting Posts

Использовать Insert или Replace в ContentProvider

Когда я хочу проверить и посмотреть, существует ли что-то в моем ContentProvider что я обычно делаю, это нечто похожее на это

 Cursor c = getContentResolver().query(table,projection,selection,selectionArgs,sort); if(c != null && c.moveToFirst()){ //item exists so update }else{ //item does not exist so insert } 

Но это означает, что я всегда должен сделать возможный ненужный вызов базы данных, замедляющий работу, особенно большее количество проверок в базе данных, которую мне нужно сделать. Должен быть лучший способ справиться с этим, поэтому я не всегда должен сначала запрашивать.

Я посмотрел на этот вопрос

Android Contentprovider – обновление в методе вставки

Но использование insertWithOnConflict проверяет только идентификатор первичного ключа, и в моем случае это не будет работать, потому что я проверяю не идентификатор, а уникальную строку из базы данных сервера.

Так что я могу сделать с поставщиком контента, поэтому мне не всегда нужно делать запрос, чтобы проверить, существует ли элемент в нем уже?

Solutions Collecting From Web of "Использовать Insert или Replace в ContentProvider"

У вас может быть ограничение UNIQUE на столбцах, отличных от ID-1. Пример:

CREATE TABLE TEST (_id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER NOT NULL, name TEXT, UNIQUE(server_id))

Имея эту таблицу, в методе вставки вашего Content Provider вы можете сделать что-то вроде этого:

 @Override public Uri insert(Uri uri, ContentValues contentValues) { final SQLiteDatabase db = mDatabase.getWritableDatabase(); final int match = mUriMathcer.match(uri); switch (match) { case TEST: insertOrUpdateById(db, uri, "TEST", contentValues, "server_id"); getContext().getContentResolver().notifyChange(uri, null, false); return Contract.Test.buildTestUri(contentValues.getAsString("server_id")); default: throw new UnsupportedOperationException("Unknown uri: " + uri); } } /** * In case of a conflict when inserting the values, another update query is sent. * * @param db Database to insert to. * @param uri Content provider uri. * @param table Table to insert to. * @param values The values to insert to. * @param column Column to identify the object. * @throws android.database.SQLException */ private void insertOrUpdateById(SQLiteDatabase db, Uri uri, String table, ContentValues values, String column) throws SQLException { try { db.insertOrThrow(table, null, values); } catch (SQLiteConstraintException e) { int nrRows = update(uri, values, column + "=?", new String[]{values.getAsString(column)}); if (nrRows == 0) throw e; } } 

Я надеюсь, что это помогает. Ура!

Ответ Эди Болоса можно просто написать как

CREATE TABLE TEST ( _id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER NOT NULL, name TEXT UNIQUE ON CONFLICT REPLACE);

Добавьте UNIQUE ON CONFLICT REPLACE в запрос создания таблицы.

Ответ Эди Болоса можно снова записать как

 private void insertOrUpdateById(SQLiteDatabase db, Uri uri, String table, ContentValues values, String column) throws Exception { long id = db.insertWithOnConflict(table, column, values, SQLiteDatabase.CONFLICT_REPLACE); if(id < 0){ throw new Exception(); } }