I’ve been reading Predictably Irrational, a book on how we tend to make stupid (irrational) decisions. In particular, we have a habit of keeping as many doors open as possible, even if doing so is to our disadvantage. So what the heck does that have to do with asynchronous database operations? Keep reading.
In the previous post, we created a grammar for parsing tasks. Now we need a database to store the tasks. In Android, this is pretty straightforward—we decided to hide the database behind a ContentProvider. (That way if we decide to open up the database to other apps in the future, we’re more than half way there.) Creating a database and a content provider in Android is well-documented. (You can also check out the classes in the
com.frankandrobot.reminderer.database package at github.)
So far so good—straightforward and simple. Then it came time to integrate the database operations (CRUD) with the UI.
The problem is that the database operations can take a relatively long time and make the app appear sluggish. The worst case scenario is that we get the dreaded ANR dialog. We need to do the CRUD in a separate thread. Android gives you several options to do this. Among them are:
- LoaderManager – as far as I can tell this is for queries only.
- AsyncQueryHandler – convenience class for running asynchronous CRUD operations based on the Handler class.
Options. So many options. And I wanted more!
When I got to this point, I was worried that the AsyncQueryHandler (being a handler) would get stopped or paused when the activity is stopped or paused. Instead of creating a simple test case to prove or disprove my theory, I proceeded to devour the stock Calendar app source code. Two weeks later, I found that it uses an IntentService in conjunction with a handler to do (some) of the CRUD.
The jury is still out on this handler-intent-service combination. But I can tell you this much—an AsyncQueryHandler does not get killed or paused when the activity gets killed or paused. (I had misunderstood the handler-activity relationship. Apparently, a handler’s life cycle isn’t as dependent on the activity’s life cycle as I thought.) So an extra two weeks later, the Reminderer app now has a working database backend. On the plus side, I am now wiser 🙂
The moral of the story is that we need to find a balance between accumulating knowledge and sticking to a schedule.
Check out the progress of the Reminderer app over at github.