Thursday, April 11, 2013

Extending Dobjanschi - An Attempt at an Android REST Client Pattern


I've been working on several mobile apps, most of them needing some way to communicate with services of the REST variety. This is an incredibly useful talk from Google I/O 2010 by Virgil Dobjanschi - if you make RESTful clients and haven't seen it, I recommend you find an hour to watch it and then find considerably longer to digest it.

Google I/O 2010 video and presentation materials here.

The pattern that really jumped at me was B: the idea of sending everything through the Content Provider. So I started making a 'simple' POC that quickly grew out of control. Without going into the development details TOO much at this point, I was stuck on two points:

  • I didn't like the idea that my CRUD calls to the Content Provider were either hitting a service, or hitting a local database. I wanted to distinguish them.
  • When Dobjanschi made his talk, Loaders didn't exist yet.

In the end, I created a pattern that was something of an amalgam of A and B: I've attempted to draw it here.

To explain in words:

  • Your activity/fragment inits a Cursor Loader and assigns something (probably itself) as a callback.
  • Your activity/fragment creates an adapter - probably ideally something that extends CursorAdapter - and assigns it to your listviews, etc.
  • Any time your activity/fragment needs to DO something (even w/o user interaction, like making a refresh request on load) it calls into your Content Manager.
  • Content Manager crafts your intent and fires it off to your Service Helper.
  • Service Helper, a singleton, tracks existing calls. If your call is a 'new' one not already running, it fires it off to the Service - which uses Intent Filters.
  • The Service (which maybe or maybe not has a queue of requests and processes them one at a time) makes your REST params, spins up a new thread, and passes them to the REST Method.
  • The REST Method handles the HTTP request/response calls, and sends the raw data to the Processor.
  • The Processor munges response data into some Content Provider-centric logic (either DTOs, or if you prefer straight to ContentValues) and makes the CRUD calls into the CP to make your database reflect the results.
  • After finishing, the Processor notifies the Content Resolver of new data. This can also be done pre- or post- HTTP request/response, if you want to show the loading process to the user. (In which case, the REST Method will need to call the Processor during each step.)
  • Because you already registered your UI components, the rest is 'magic': your adapter will find the new data and refresh the UI automatically.
This assumes a SQLite database behind your Content Provider - I put another layer between my CP and my DB and called it "__DataSource" - my CP handles the URI routing to different DataSource methods while DataSource handles the actual heavy lifting (making queries, parsing ContentValues, etc). I've also found it handy for my DTOs to have 'fromCursor' methods on them - makes it very easy for my adapter to do something like "view.bind(Data.fromCursor(cursor));" in bindView.

Hopefully this gives some good direction on how I've gone about implementing a responsive client. I feel the pattern is good enough that it works beyond REST - any long-running async calls would likewise benefit from something like this, and it keeps you from having to constantly know WHEN to update the front end. You just bind it, and walk away: whenever the data changes, you sound off to the Content Resolver and any active pieces that care come running.

Up next (soon I hope) I'll discuss using an in-memory-only "database" for your Content Provider repo.

Happy coding!