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?


I like writing code that uses KISS (Keep It Simple Stupid). For me, KISS means that each class does one thing and one thing well. No “swiss-army knife” classes, no convoluted methods that do everything and anything. KISS applied to code usually results in code that’s easy to understand and maintain.

It was obvious that the database would need to do things the Android way. Not only for performance but also to make it easier to understand and maintain. Yeah, you read that right. Imagine yourself going back to a project after several months. Using Android classes and frameworks (and in the intended way) means you’ll spend less time relearning the project.

Android has the peculiar property that it restarts applications when the user does something “unexpected” like putting the phone on its side. The database framework would need to handle configuration changes. (Imagine, for example, rotating the phone while updating hundreds of tasks.)

It also goes without saying that the database framework would need to run on a thread other than the UI. (Imagine, for example, updating hundreds of tasks. You’ll get an ANR if it takes more than 5 seconds.)

Design Principles

Putting it all together, here are the guiding principles for the new database framework:

  1. It should be easy to understand and maintain. Use existing Android classes whenever possible.
  2. It should be generic enough so that the “database” can be a sqlite database or something else.
  3. It should know about configuration changes (like changing the phone orientation).
  4. It should be multi-thread safe. By “thread safe”:
    1. it should NOT run in the main UI thread,
    2. database calls should not conflict with each other
    3. the system should know how to communicate results back to the main UI thread.

The New Database Framework

First, what does NOT work:

The new system is based on AsyncTaskLoader. It’s actually pretty simple:

  • a TaskContentProvider provides low-level access to the database. All the CRUD and only the CRUD.
  • a TaskDatabaseFacade provides hi-level access to the database. So, for example, the createTask method not only creates a task using TaskContentProvider, it also updates the alarm system. (In other words, the TaskDatabaseFacade is the CRUD + business logic.) TaskDatabaseFacade is actually a collection of AsyncTaskLoaders, one per action.

And that’s it! If I need to store the database somewhere else (say Google drive or Dropbox), TaskDatabaseFacade can use a different loader. If I need to open up the ContentProvider to the rest of the Android system, I can just implement another one (remember KISS).

Handling multi-threading is still a work in progress. Before HoneyComb, all loaders run in parallel, leading to data consistency issues if you don’t handle multi-threading correctly. After HoneyComb, it’s still an issue if you run another background thread that updates the database at the same time as the UI.

That’s basically it. Checkout the work in progress in the newDB branch over at GitHub. It’s currently more of a proof of concept—insertion and reads work.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s