Grokking Android

Getting Down to the Nitty Gritty of Android Development

Android’s ContentProviderOperation: “withYieldAllowed” explained

By

Whenever you use a ContentProviderOperation and have to insert, update or delete many records, the method withYieldAllowed() comes in handy.

Normally the batch job would be executed in one transaction that spans all operations. But if your job contains many manipulations, the transaction might last quite a while and it might block other tasks from being executed. This can be an issue, especially if you use standard content providers like ContactsContract or CalendarContract that might be used by many apps and background services (e.g. sync adapters) at the same time.

The method withYieldAllowed() of the nested class ContentproviderOperation.Builder deals with this problem. Alas what this method does is not documented on the class itself. It is documented – just somewhere else 🙂

What this method does, can be found within the documentation to ContactsContract's inner class Data:

The flip side of using batched operations is that a large batch may lock up the database for a long time preventing other applications from accessing data and potentially causing ANRs ("Application Not Responding" dialogs.)

To avoid such lockups of the database, make sure to insert "yield points" in the batch. A yield point indicates to the content provider that before executing the next operation it can commit the changes that have already been made, yield to other requests, open another transaction and continue processing operations. A yield point will not automatically commit the transaction, but only if there is another request waiting on the database. Normally a sync adapter should insert a yield point at the beginning of each raw contact operation sequence in the batch.

So whenever you have operations within your batch job that must be executed together but that are independent of the following tasks add a withYieldAllowed() at the beginning of each of these logical blocks. — I edited the previous sentence after amay82 asked the question in the comments below.

Say you add multiple appointments as a sync adapter. In this case you will add an records to events, to instances and probably to reminders. All these must be executed within one transaction for each event. But it is not necessary to execute all events in one transaction. You can sync the other events later on, if something goes awry.

Of course one transaction is faster. So Android will not necessarily commit your transaction at every yield point. Instead it does so only if necessary.

I have filed a bug report asking for an appropriate documentation of this method. Please star the issue so that it get's fixed faster.

What's your take of the documentation? What is missing? What is insufficiently explained? And where does it excel?

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.