ContentProviders are one of Android's core building blocks. They represent a relational interface to data - either in databases or (cached) data from the cloud.
Sometimes you want to use them for multiple operations in a row. Like updating different sources and so on. In those cases you could call the respective ContentResolver
methods multiple times or you could execute a batch of operations. The latter is the recommended practise.
To create, delete or update a set of data in a batch like fashion you should use the class ContentProviderOperation
.
According to Android's documentation it is recommended to use ContentProviderOperations
for multiple reasons:
- All operations execute within the same transaction - thus data integrity is assured
- This helps improve performance since starting, running and closing one transaction offers far better performance than opening and committing multiple transactions
- Finally using one batch operation instead of multiple isolated operations reduces the number of context switches between your app and the content provider you are using. This of course also helps to improve the performance of your app - and by using less cpu cycles also reduces the power consumption.
To create an object of ContentProviderOperation
you need to build it using the inner class ContentProviderOperation.Builder
. You obtain an object of the Builder class by calling one of the three static methods newInsert
, newUpdate
or newDelete
:
Method | Usage |
---|---|
newInsert | Create a Builder object suitable for an insert operation |
newUpdate | Create a Builder object suitable for an update operation |
newDelete | Create a Builder object suitable for a delete operation |
The Builder is an example of the Gang of Four Builder pattern. A Builder defines an interface for how to create objects. Concrete instances then create specific objects for the task at hand. In this case we have three different Builders for creating ContentProviderOperation
objects. These objects can be used to create, update or delete ContentProvider data sets.
Typically all steps necessary to create a ContentProviderOperation object are done in one round of method chaining. That's possible because all methods of the Builder
class return a Builder
object themself. The one exception is the build()
method, which instead returns the desired object: Our completely created ContentProviderOperation
object. So a typical chain might look like this:
ArrayList<ContentProviderOperation> ops =
new ArrayList<ContentProviderOperation>();
ops.add(
ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
.withValue(RawContacts.ACCOUNT_TYPE, "someAccountType")
.withValue(RawContacts.ACCOUNT_NAME, "someAccountName")
.withYieldAllowed(true)
.build());
Of course you could also use a ContentValues object as usual and use the withValues(values)
method instead.
The Builder class has among others these methods you can use to define which objects to delete or how to create or update an object:
Method | Usage |
---|---|
withSelection (String selection, String[] selectionArgs) | Specifies on which subset of the existing data set to operate. Only usable with ContentProviderOperation objects used to update or delete data |
withValue (String key, Object value) | Defines the desired value for one column. Only usable with ContentProviderOperation objects used to create or update data |
withValues (ContentValues values) | Defines the desired values for multiple columns. Only usable with ContentProviderOperation objects used to create or update data |
As you can see in the code sample I presented above you need an ArrayList
of ContentProviderOperation
objects. For every ContentProvider-CRUD method you have to use one ContentProviderOperation object and add it to this list. I will explain in a later blog post about the method withValueBackReference()
why it has to be an ArrayList and not say a LinkedList
.
The list is finally passed to the applyBatch()
method of the ContentResolver object:
try {
getContentResolver().
applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException e) {
// do s.th.
} catch (OperationApplicationException e) {
// do s.th.
}
That's all for now. I will explain two methods of the Builder class, that are not well documented, in separate follow up posts.