01Aug

Presentation

DataDroid was an Android Library which will ease the developement of Android applications when you have to manage local data or to call REST webservices for remote data. It is compatible with 2.2+ applications.
This project is still available on GitHub but is now deprecated.

During the Google I/O 2010, a session was aired about how to handle REST webservices in an Android application. For those who didn’t see it yet, here is the video of the presentation :

This presentation was really interesting but unforTunately it was only theorical and didn’t include any code to help the developers to implement the solutions proposed. DataDroid allows you to easily implement the first solution shown in the session.

Features

Before showing how to add DataDroid to your project, let’s see what you will be able to do with it :

  • Local data management in a SQLite database
  • Local data management in memory
  • REST Webservices calls with management of configuration changes (orientation for example) and Activities hiding for a phone call for example

The project contains :

  • The Android Library containing all the classes needed
  • A proof-of-concept project containing samples of code using the Android Library for the different use cases explained here

Architecture

Here is what’s happening when you makes a webservice call using DataDroid :

(click the image to see it in full size)

  1. The Activity create a Request (in this example using a RequestFactory).
    The Request object contains the following data :
    • A request type (integer) allowing you to distinguish the different type of Requests you have.
    • A boolean to know whether to save the data received from the Operation in the memory cache or not
    • Parameters for the request (key => value pattern)
  2. The Activity calls the execute() method of RequestManager.
    In the method, a check is automatically made to see if the same request call is already in progress.
    • If it’s the case, the given RequestListener is added to the current request call.
    • Otherwise a new request call is also created.
  3. The RequestManager forwards the Request to the RequestService if it's not already in progress.
  4. The RequestService creates the Operation corresponding to the received request type and gives it the Request.
  5. The Operation uses the provided NetworkConnection class to make the webservice request and parse the result.
    • If a connection error occurs during the webservice call, it is sent back to the RequestManager. And it will be transmitted to the RequestListener (more information about that below).
    • Same thing for a data error while parsing the data or saving the data in the database
    • You can also if needed throw a CustomRequestException. In this case, you are getting called back in the RequestService if you have overridden the method onCustomRequestException().
      This allows you to provide additional information based on the exception you threw. As for the connection error, it is sent back the RequestManager and then to the RequestListener.
  6. Depending on your case, you can then either save your data in a ContentProvider or send it back to the calling Activity using Parcelable objects.
    • If you save your data in a ContentProvider, you can use a CursorLoader in your Activity to retrieve your data.
    • If you use Parcelable objects, you just have to add them to the returned Bundle.
      You should also set the flag in your Request to cache your data in memory.
  7. Finally a RequestListener callback is called from the RequestManager :
    • onRequestFinished(request, resultData) if the request was executed without problems.
    • onRequestConnectionError(request, statusCode) if a connection error occurred while executing the request.
    • onRequestDataError(request) if a data error occurred while executing the request.
    • onRequestCustomError(request, resultData) if a CustomRequestException was thrown during the execution of the request.
      in this case, resultData contains the additional information provided if you have overridden the method onCustomRequestException().

If your Activity was not listening anymore when the request finished its execution (for example a phone call is currently occurring), you will not be called back as you have unregistered your listener in the onPause() method.
On your next onResume() when you want to register again your listener, you can check if your request is still in progress using the isRequestInProgress(request) method of RequestManager.

  • If that's the case, just register again your listener.
  • Otherwise, if you have enabled the memory cache for your request (ie you are using Parcelable objects), you can use the callListenerWithCachedData(requestListener, request) method.
    • If there is some cached data available, the method onRequestFinished(request, resultData) of the listener will be called with the cached data.
    • Otherwise the method onRequestConnectionError(request, statusCode) will be called.
All these features are presented in different examples in the sample project provided with the library.

20 Responses to “Presentation”

  1. [...] en cours d’envoi. Une description complète est disponible sur le site de la librairie : http://datadroid.foxykeep.com/presentation. A noter que plusieurs exemples sont disponibles via l’application DataDroid PoC que vous pouvez [...]

  2. [...] en cours d’envoi.Pour consulter une description complète de DataDroid voici le lien : (link)Pour l’installation voici le lien : (link)  Share and Enjoy: TweetRelated [...]

  3. snicolas (1 comments) says:

    Bravo pour cette nouvelle release. On dirait bien que RoboSpice a un concurrent sérieux :)

    Félicitations !
    Stéphane

  4. Miguel (3 comments) says:

    Hi foxykeep, first of all thank you for the library, I’ve been reading a lot these days and I find your architecture & implementation the most robust. Cyril Mottier forking it definetely convinced me!

    On the DB persistence topic, from what I understand it should be done inside the Operation’s execute(), right? I’d get access to the content provider through the context and insert/delete/update

    I’m asking because I couldn’t find an Operation that does this in the example project.

    Thanks again!

    btw: this comment box looks horrible on Chrome@Mac. Overlaps everywhere.

  5. Miguel (3 comments) says:

    Also, I’m considering getting rid of the ContentProvider as I don’t intend to share any content from my app. I’d access the DB directly in the Operation and use a custom CursorLoader that doesn’t need a ContentProvider.

    Any advice against this path?

    Thanks again!

  6. Miguel (3 comments) says:

    Ok, I just noticed you already explain it in this post. Sorry for not reading before.

    Anyway, the question about not using a contentprovider is still there.

    Thanks and sorry for the spam.

    • foxykeep (19 comments) says:

      About an example Operation using a ContentProvider, you can check PersonListOperation in the sample project.

      About using direct DB access instead of a ContentProvider, I have nothing against it. I just found using a ContentProvider cleaner and simpler (especially if you use my ContentProviderCodeGenerator to write all the code for you ^^)

  7. Carolina (1 comments) says:

    Hi foxykeep,

    I have been looking at your datadroid library and I have been playing with the datadroidpoc application, in particular the Person List (DB).

    I have a question which I’m unable to figure out how to answer…
    Say for example that a Person has name, address, AND a list of rental properties.
    The list of rental properties could potentially be from 1 to thousands.
    Let’s assume that rental properties can not be shared among different people.

    Here are my questions:
    1. in the database, should the rental property data be in a separate table RENTALPROPERTY and somehow there should be an association between the PERSON table and the RENTALPROPERTY table. Correct?

    2. I’m not sure how I would implement that in the Person List example. Could you please give me ideas?

    3. If I wanted to display the Person list in an expandable list with name and address first and then when a specific person is clicked, I would display the list of rental properties. In that case, when displaying the person list, would the list of rental properties for each person fetched from the database be also fetched (even if I’m not displaying until a specific person is clicked)?

    4. Is there a way to only load and query the list of property rentals only when a person is selected?

    Any ideas would be greatly appreciated.

  8. Eugene (5 comments) says:

    Hello foxykeep,

    I’m writing an app using DataDroid and can’t seem to find how to edit Body of request (method: PUT). Need to execute smth like this:

    PUT …/vmrest/messages/

    false

    Does it support request body editing at all?

    thanks

  9. Eugene (5 comments) says:

    in prev. post after “smth like this:” should be

    PUT /vmrest/messages/messageid
    -Message-
    -Subject-New subject-/Subject-
    -/Message-

    • foxykeep (19 comments) says:

      Update your datadroid version to the latest one on GitHub. I’ve just uploaded this morning a fix for this use case. There is now a setPostText(String text, Method method) method in NetworkConnection which allows you to use PUT method with post data.

  10. Eugene (5 comments) says:

    thanks
    worked like a charm

  11. Marco (1 comments) says:

    The perfect project!!!!

    The best code i have seen.

    Thank you VERY much!!!!

  12. vladimir (3 comments) says:

    Hello,

    Is it possible to implement pattern B (Activity – ContentProvider – Service) and pattern C (Activity – ContentProvider – SyncAdapter) with DataDroid lib?

    Thanks

    • foxykeep (19 comments) says:

      Not with the current implementation. It was built around pattern A. So you’ll have to modify it quite a bit if you want to follow pattern B/C

      • vladimir (3 comments) says:

        Can you please give me a hint about modification which should be done in order to implement pattern B.
        I really confused…

        Thanks

        • foxykeep (19 comments) says:

          I have no idea how to implement the pattern B :/ DataDroid was only meant to work with pattern A. So I know that if you want to implement pattern B, you have a lot of stuff to change but I don’t know how :/