How to implement a simple REST and ContentProvider architecture using Models?

android, java, rest

Solution

Have you considered using an ORM? I've had success with a combination of OrmLite and Jackson in the past. You will have to write your own service for synchronization, but OrmLite takes care of the heavy lifting when it comes to your data models.

Although you won't get some of the niceties that the ContentProvider + SyncAdapter combination provides (still no CursorLoader when you're using POJOs), this setup may ease the burden of a complex schema and/or lots of types.

Here's an example of a table definition from OrmLite's homepage:

@DatabaseTable(tableName = "accounts")
public class Account {
    @DatabaseField(id = true)
    private String name;

    @DatabaseField(canBeNull = false)
    private String password;   
}

As you can see, the model + mapping + table definition comes together very quickly and painlessly.

Problem

I'm currently developing an android app that interacts with a RESTful webservice. The client is able to perform full CRUD on the webservice. After searching for best practices I watched the Google I/O 2010 keynote about REST clients which is cited in almost all articles. To use as much of the android platform as possible, I decided to go with Option B using a `ContentProvider` and a `SyncAdapter`. This provided me with the built-in account system, content observers and periodic syncs when internet is availble. Because one very important feature of our App is offline editing and availability (it is used in environments with bad reception) we want to keep as much relevant data locally as possible. The client communicates with the server using a RESTful API in Json, the data from the server is deserialized using Gson on Models (POJO's, Plain old java objects). To keep the code clear and easy to read I tried building my own object mapper instead of using a `Cursor` directly. This mapper provides default CRUD-operations and maps Cursors to Models when reading data and Models to ContentValues when writing data. However, this architecture feels very bloated. First of all it is not possible to get reliable information about the current `SyncState` (to provide feedback to the user). (Now "hacked" using this SO answer) The second problem is that for each resource I will need: A model, A mapper, A table definition and ContentProvider URIs. Which is a lot of code to manage for just one resource. The third problem is that requiring Models through my mapper I blocked myself from using a `CursorLoader` in the Activities. Bottom line I'm looking for a maintainable and lightweight way of having offline content and synchronisation with a RESTful webservice using Json. Also I would like to be able to use Models in my code because `user.getName()` is a lot more developer friendly than `cursor.getString(cursor.getColumnIndex(UserDataSource.COLUMN_NAME));` (Which is currently hidden in my Mapper class). A good example on mapping would be Dapper combined with Dapper Extensions written for .NET but similar to my approach, however my approach required all columns and fields to be defined in many different files (see above). Also, I'm considering to drop the `ContentProvider` from my code because it feels very bloated and obsolete for such a simple task.

Original source

Related problems