Client Android REST, Sample?

Même si ce fil a accepté la réponse, n’hésitez pas à proposer d’autres idées, vous utilisez ou aimez


J’ai rencontré ces articles:

  • Service API Restful
  • API client Java REST pour Android

Et cela m’a conduit à cette vidéo Google I / O 2010 sur les applications clientes REST

  • http://www.youtube.com/watch?v=xHXn3Kg2IQE&feature=player_embedded

Depuis, j’ai créé un composant REST en tant que composant statique dans ma classe de contrôleur d’application.

À partir de maintenant, je pense que je devrais changer de modèle. Quelqu’un a fait remarquer que l’application Google IOSched est un excellent exemple de la façon d’écrire des clients REST sur Android. Quelqu’un d’autre a dit que cela était trop compliqué.

Alors, quelqu’un peut-il nous montrer quelle est la meilleure pratique? De manière simple et rapide.
L’application IOSched est trop complexe pour des exemples de cas d’utilisation.

EDIT 2 (octobre 2017):

Nous sums en 2017. Utilisez simplement Retrofit. Il n’y a presque aucune raison d’utiliser autre chose.

MODIFIER:

La réponse originale est plus d’un an et demi au moment de cette édition. Bien que les concepts présentés dans la réponse originale soient toujours valables, comme le soulignent d’autres réponses, il existe maintenant des bibliothèques qui facilitent cette tâche. Plus important encore, certaines de ces bibliothèques gèrent les modifications de configuration des périphériques pour vous.

La réponse originale est conservée ci-dessous pour référence. Mais s’il vous plaît, prenez le temps d’examiner certaines des bibliothèques de clients Rest pour Android pour voir si elles correspondent à vos cas d’utilisation. Voici une liste de certaines des bibliothèques que j’ai évaluées. Il ne s’agit en aucun cas d’une liste exhaustive.

  • Volley (c’est de Google)
  • RESTDroid
  • RoboSpice
  • Rénovation

Réponse originale:

Présenter mon approche pour avoir des clients REST sur Android. Je ne prétends pas que ce soit le meilleur cependant 🙂 Notez également que c’est ce que j’ai proposé en réponse à mes exigences. Vous devrez peut-être avoir plus de couches / append plus de complexité si votre cas d’utilisation l’exige. Par exemple, je n’ai pas de stockage local du tout; parce que mon application peut tolérer la perte de quelques réponses REST.

Mon approche utilise uniquement AsyncTask s sous les couvertures. Dans mon cas, je “appelle” ces tâches depuis mon instance d’ Activity ; mais pour prendre pleinement en compte les cas tels que la rotation de l’écran, vous pouvez choisir de les appeler depuis un Service ou autre.

J’ai consciemment choisi mon client REST comme API. Cela signifie que l’application qui utilise mon client REST n’a même pas besoin de connaître les URL REST réelles et le format de données utilisé.

Le client aurait 2 couches:

  1. Couche supérieure: cette couche a pour but de fournir des méthodes qui reflètent les fonctionnalités de l’API REST. Par exemple, vous pouvez avoir une méthode Java correspondant à chaque URL de votre API REST (ou même deux – une pour les GET et une pour les POST).
    C’est le point d’entrée dans l’API client REST. C’est la couche que l’application utilisera normalement. Ce pourrait être un singleton, mais pas nécessairement.
    La réponse de l’appel REST est analysée par cette couche dans un object POJO et renvoyée à l’application.

  2. Il s’agit de la couche AsyncTask niveau inférieur, qui utilise les méthodes du client HTTP pour sortir et effectuer cet appel REST.

De plus, j’ai choisi d’utiliser un mécanisme de AsyncTask pour communiquer le résultat de l’ AsyncTask à l’application.

Assez de texte. Voyons maintenant du code. Prenons une hypothétique URL de l’API REST – http://myhypotheticalapi.com/user/profile

La couche supérieure pourrait ressembler à ceci:

  /** * Entry point into the API. */ public class HypotheticalApi{ public static HypotheticalApi getInstance(){ //Choose an appropriate creation strategy. } /** * Request a User Profile from the REST server. * @param userName The user name for which the profile is to be requested. * @param callback Callback to execute when the profile is available. */ public void getUserProfile(Ssortingng userName, final GetResponseCallback callback){ Ssortingng restUrl = Utils.constructRestUrlForProfile(userName); new GetTask(restUrl, new RestTaskCallback (){ @Override public void onTaskComplete(Ssortingng response){ Profile profile = Utils.parseResponseAsProfile(response); callback.onDataReceived(profile); } }).execute(); } /** * Submit a user profile to the server. * @param profile The profile to submit * @param callback The callback to execute when submission status is available. */ public void postUserProfile(Profile profile, final PostCallback callback){ Ssortingng restUrl = Utils.constructRestUrlForProfile(profile); Ssortingng requestBody = Utils.serializeProfileAsSsortingng(profile); new PostTask(restUrl, requestBody, new RestTaskCallback(){ public void onTaskComplete(Ssortingng response){ callback.onPostSuccess(); } }).execute(); } } /** * Class definition for a callback to be invoked when the response data for the * GET call is available. */ public abstract class GetResponseCallback{ /** * Called when the response data for the REST call is ready. 
* This method is guaranteed to execute on the UI thread. * * @param profile The {@code Profile} that was received from the server. */ abstract void onDataReceived(Profile profile); /* * Additional methods like onPreGet() or onFailure() can be added with default implementations. * This is why this has been made and abstract class rather than Interface. */ } /** * * Class definition for a callback to be invoked when the response for the data * submission is available. * */ public abstract class PostCallback{ /** * Called when a POST success response is received.
* This method is guaranteed to execute on the UI thread. */ public abstract void onPostSuccess(); }

Notez que l’application n’utilise pas le JSON ou le XML (ou tout autre format) renvoyé directement par l’API REST. Au lieu de cela, l’application ne voit que le Profile bean.

Ensuite, le calque inférieur (couche AsyncTask) pourrait ressembler à ceci:

 /** * An AsyncTask implementation for performing GETs on the Hypothetical REST APIs. */ public class GetTask extends AsyncTask{ private Ssortingng mRestUrl; private RestTaskCallback mCallback; /** * Creates a new instance of GetTask with the specified URL and callback. * * @param restUrl The URL for the REST API. * @param callback The callback to be invoked when the HTTP request * completes. * */ public GetTask(Ssortingng restUrl, RestTaskCallback callback){ this.mRestUrl = restUrl; this.mCallback = callback; } @Override protected Ssortingng doInBackground(Ssortingng... params) { Ssortingng response = null; //Use HTTP Client APIs to make the call. //Return the HTTP Response body here. return response; } @Override protected void onPostExecute(Ssortingng result) { mCallback.onTaskComplete(result); super.onPostExecute(result); } } /** * An AsyncTask implementation for performing POSTs on the Hypothetical REST APIs. */ public class PostTask extends AsyncTask{ private Ssortingng mRestUrl; private RestTaskCallback mCallback; private Ssortingng mRequestBody; /** * Creates a new instance of PostTask with the specified URL, callback, and * request body. * * @param restUrl The URL for the REST API. * @param callback The callback to be invoked when the HTTP request * completes. * @param requestBody The body of the POST request. * */ public PostTask(Ssortingng restUrl, Ssortingng requestBody, RestTaskCallback callback){ this.mRestUrl = restUrl; this.mRequestBody = requestBody; this.mCallback = callback; } @Override protected Ssortingng doInBackground(Ssortingng... arg0) { //Use HTTP client API's to do the POST //Return response. } @Override protected void onPostExecute(Ssortingng result) { mCallback.onTaskComplete(result); super.onPostExecute(result); } } /** * Class definition for a callback to be invoked when the HTTP request * representing the REST API Call completes. */ public abstract class RestTaskCallback{ /** * Called when the HTTP request completes. * * @param result The result of the HTTP request. */ public abstract void onTaskComplete(Ssortingng result); } 

Voici comment une application peut utiliser l’API (dans une Activity ou un Service ):

 HypotheticalApi myApi = HypotheticalApi.getInstance(); myApi.getUserProfile("techie.curious", new GetResponseCallback() { @Override void onDataReceived(Profile profile) { //Use the profile to display it on screen, etc. } }); Profile newProfile = new Profile(); myApi.postUserProfile(newProfile, new PostCallback() { @Override public void onPostSuccess() { //Display Success } }); 

J’espère que les commentaires suffisent pour expliquer la conception; mais je serais heureux de fournir plus d’informations.

“Développer des applications clientes Android REST” par Virgil Dobjanschi a suscité de nombreuses discussions, car aucun code source n’a été présenté pendant la session ou a été fourni ultérieurement.

La seule implémentation de référence que je connaisse (merci de commenter si vous en savez plus) est disponible sur Datadroid (la session Google IO est mentionnée sous / presentation). C’est une bibliothèque que vous pouvez utiliser dans votre propre application.

Le second lien demande le “meilleur” framework REST, qui est largement discuté sur stackoverflow. Pour moi, la taille de l’application est importante, suivie de la performance de l’implémentation.

  • Normalement, j’utilise l’implemantation plain org.json, qui fait partie d’Android depuis l’API niveau 1 et n’augmente donc pas la taille de l’application.
  • Pour moi, les informations trouvées sur les performances des parsingurs JSON dans les commentaires étaient très intéressantes: à partir d’Android 3.0 Honeycomb, l’parsingur de streaming de GSON est inclus sous android.util.JsonReader. Malheureusement, les commentaires ne sont plus disponibles.
  • Spring Android (que j’utilise parfois) prend en charge Jackson et GSON. La documentation du module Spring Android RestTemplate pointe vers un exemple d’application .

Par conséquent, je m’en tiens à org.json ou GSON pour des scénarios plus complexes. Pour l’architecture d’une implémentation org.json, j’utilise une classe statique qui représente les cas d’utilisation du serveur (par exemple findPerson, getPerson). J’appelle cette fonctionnalité à partir d’un service et j’utilise les classes d’utilitaires qui effectuent le mappage (spécifique au projet) et le réseau IO (mon propre modèle REST pour plain GET ou POST). J’essaie d’éviter l’usage de la reflection.

N’utilisez jamais AsynTask pour effectuer une requête réseau ou tout ce qui doit être persistant. Async Task est fortement lié à votre activité et si l’utilisateur change l’orientation de l’écran depuis la création de l’application, AsyncTask sera arrêté.

Je vous suggère d’utiliser le modèle de service avec Intent Service et ResultReceiver. Jetez un oeil à RESTDroid . C’est une bibliothèque qui vous permet d’effectuer n’importe quel type de demande REST de manière asynchrone et d’informer votre interface utilisateur des écouteurs de requêtes implémentant le modèle de service de Virgil Dobjanschi.

Il existe une autre bibliothèque avec des données API et des données de type beaucoup plus propres. https://github.com/kodart/Httpzoid

Voici un exemple d’utilisation simple

 Http http = HttpFactory.create(context); http.post("http://example.com/users") .data(new User("John")) .execute(); 

Ou plus complexe avec des rappels

 Http http = HttpFactory.create(context); http.post("http://example.com/users") .data(new User("John")) .handler(new ResponseHandler() { @Override public void success(Void ignore, HttpResponse response) { } @Override public void error(Ssortingng message, HttpResponse response) { } @Override public void failure(NetworkError error) { } @Override public void complete() { } }).execute(); 

C’est nouveau, mais il semble très prometteur.

Il existe de nombreuses bibliothèques et j’utilise celle-ci: https://github.com/nerde/rest-resource . Ceci a été créé par moi et, comme vous pouvez le voir dans la documentation, il est beaucoup plus propre et plus simple que les autres. Ce n’est pas centré sur Android, mais je l’utilise et ça marche plutôt bien.

Il prend en charge HTTP Basic Auth. Il effectue le sale travail de sérialisation et de désérialisation des objects JSON. Vous l’aimerez, surtout si votre API est comme Rails.

Disclaimer: Je suis impliqué dans le projet open source rest2mobile

Une autre alternative en tant que client REST consiste à utiliser rest2mobile .

L’approche est légèrement différente car elle utilise des exemples de repos concrets pour générer le code client du service REST. Le code remplace l’URL REST et les données utiles JSON par des méthodes Java et des POJO natifs. Il gère également automatiquement les connexions serveur, les appels asynchrones et les conversions JSON POJO vers / depuis.

Notez que cet outil est disponible en différentes versions (cli, plugins, support Android / iOS / js) et que vous pouvez utiliser le plugin Android Studio pour générer l’API directement dans votre application.

Tout le code peut être trouvé sur github ici .