Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Insert or Replace in ContentProvider

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?

like image 530
tyczj Avatar asked May 01 '14 22:05

tyczj


People also ask

What is a ContentProvider and what is it typically used for?

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.

What is ContentProvider and ContentResolver default ContentProvider of Android?

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.

How can I access my content provider from another application?

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.


1 Answers

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!

like image 122
Eduard B. Avatar answered Sep 23 '22 05:09

Eduard B.