When I want to check and see if something exists in my ContentProvider
what I usually do is something similar to this
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
}
but that means I always have to make possibly an unnecessary Database call slowing things down especially the greater number of checks on the database I need to do. There has to be a better way to handle this so I dont always have to query first.
I looked at this question
Android Contentprovider - update within an insert method
but using insertWithOnConflict
only checks the primary key id and in my case that will not work because what I am checking is not the id but a unique string from a server database.
so is there something I can do with the Content Provider so I dont always have to make a query to check if the item exists in it already?
A content provider manages access to a central repository of data. A provider is part of an Android application, which often provides its own UI for working with the data. However, content providers are primarily intended to be used by other applications, which access the provider using a provider client object.
A content provider component supplies data from one application to others on request. Such requests are handled by the methods of the ContentResolver class. A content provider can use different ways to store its data and the data can be stored in a database, in files, or even over a network.
In order to access the content provider, the client app needs to declare permissions in the Android Manifest for that content provider. Permissions are not covered in detail in these concepts. You can learn more in Declaring Permissions, System Permissions, and Implementing Content Provider Permissions.
You can have UNIQUE constraint on columns different than ID one. Example:
CREATE TABLE TEST (_id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id INTEGER NOT NULL, name TEXT, UNIQUE(server_id))
Having this table, in the insert method of your Content Provider you can do something like this:
@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;
}
}
I hope it helps. Cheers!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With