Grokking Android

Getting Down to the Nitty Gritty of Android Development

Android: Better Performance with ContentProviderOperation

By

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:

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:

Methods to obtain a Builder object
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:

Some important methods of the Builder 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.

Wolfram Rittmeyer lives in Germany and has been developing with Java for many years.

He has been interested in Android for quite a while and has been blogging about all kind of topics around Android.

You can find him on Google+ and Twitter.