Multiple rows insert with ContentProvider

后端 未结 4 2011
醉话见心
醉话见心 2021-02-02 00:23

I need to make insert of few rows in one transaction. Can I do it with ContentProvider?

4条回答
  •  时光说笑
    2021-02-02 00:28

    I have implemented this in my app and here's the gist of the code that I use.

    In my content provider, I have overridden the applyBatch() method and it's a very simple method to override:

    /**
     * Performs the work provided in a single transaction
     */
    @Override
    public ContentProviderResult[] applyBatch(
            ArrayList operations) {
        ContentProviderResult[] result = new ContentProviderResult[operations
                .size()];
        int i = 0;
        // Opens the database object in "write" mode.
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        // Begin a transaction
        db.beginTransaction();
        try {
            for (ContentProviderOperation operation : operations) {
                // Chain the result for back references
                result[i++] = operation.apply(this, result, i);
            }
    
            db.setTransactionSuccessful();
        } catch (OperationApplicationException e) {
            Log.d(TAG, "batch failed: " + e.getLocalizedMessage());
        } finally {
            db.endTransaction();
        }
    
        return result;
    }
    

    The result is given to the next operation because you want to support back references. When I actually want to change stuff in the database in this single transaction I loop over my content and do stuff like this:

    operations.add(ContentProviderOperation
                        .newInsert(
                                Uri.withAppendedPath(
                                        NotePad.Notes.CONTENT_ID_URI_BASE,
                                        Long.toString(task.dbId)))
                        .withValues(task.toNotesContentValues(0, listDbId))
                        .build());
    // Now the other table, use back reference to the id the note
    // received
    noteIdIndex = operations.size() - 1;
    
    operations.add(ContentProviderOperation
                        .newInsert(NotePad.GTasks.CONTENT_URI)
                        .withValues(task.toGTasksContentValues(accountName))
                        .withValueBackReferences(
                                task.toGTasksBackRefContentValues(noteIdIndex))
                        .build());
    

    You just need to remember to finish by calling:

    provider.applyBatch(operations);
    

    This will perform your stuff in a single transaction and supports backreferences if you need the id from an earlier insert without issue.

提交回复
热议问题