Technology

Reminderer: Database Backend Redux


I spent last week rewriting the database backend and boy was it a convoluted mess.

First, I tried salvaging the existing framework but I couldn’t figure out what the heck it was doing. Then I tried an implementation using ThreadPools, but handling configuration changes meant re-inventing the wheel. (Re-inventing the wheels means that there’s a good chance the code might break in future Android versions.) Then I tried a version using DAOs. Unfortunately, the “Android way” (using Cursors) gives better performance, so I started again from scratch.

But what is the Android way? and what did I really want?

Continue reading

Advertisements
Technology

Reminderer: Asynchronous Database Operations (Part 2)


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:

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.