Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

java

rest

android

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.

like image 985
christiaanderidder Avatar asked Mar 21 '13 15:03

christiaanderidder


People also ask

How can an application activate ContentProvider?

Create Content Provider Next you will need to create your own database to keep the content. Usually, Android uses SQLite database and framework needs to override onCreate() method which will use SQLite Open Helper method to create or open the provider's database.

What is the content provider how it is implemented?

A content provider manages access to a central repository of data. You implement a provider as one or more classes in an Android application, along with elements in the manifest file. One of your classes implements a subclass ContentProvider , which is the interface between your provider and other applications.

What is a ContentProvider and what is it typically used for?

A content provider manages access to a central repository of data. A provider is part of an Android application, which often provides its own UI for working with the data. However, content providers are primarily intended to be used by other applications, which access the provider using a provider client object.


Video Answer


1 Answers

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.

like image 114
klmprt Avatar answered Oct 20 '22 04:10

klmprt