web-dev-qa-db-fra.com

Android REST client, Exemple?

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:

Et cela m’a amené à cette vidéo Google I/O 2010 sur REST applications client

Depuis lors, j'ai créé le 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 schéma. Quelqu'un a souligné que Google IOSched l'application est un excellent exemple de la façon d'écrire REST clients sur Android. Quelqu'un d'autre dit que cette façon de faire est trop compliquée.

Alors, quelqu'un peut-il nous montrer quelle est la meilleure pratique? En bref et simple.
L'application IOSched est trop complexe pour un exemple de cas d'utilisation.

111
Marek Sebera

EDIT 2 (octobre 2017):

Nous sommes en 2017. Il suffit d'utiliser Retrofit. Il n'y a presque aucune raison d'utiliser autre chose.

MODIFIER:

La réponse originale a plus d'un an et demi au moment de cette modification. Bien que les concepts présentés dans la réponse initiale 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 pour vous les modifications de configuration des périphériques.

La réponse originale est conservée ci-dessous pour référence. Mais prenez également le temps d'examiner certaines des bibliothèques clientes Rest pour Android afin de voir si elles correspondent à vos cas d'utilisation. Ce qui suit est une liste de certaines des bibliothèques que j'ai évaluées. Il ne s'agit en aucun cas d'une liste exhaustive.


Réponse originale:

Présentation de mon approche consistant à avoir REST clients sur Android. Je ne prétends pas que ce soit le meilleur cependant :) Notez également que c’est ce que j’ai trouvé en réponse à mes besoins. Vous aurez peut-être besoin d'avoir plus de couches/d'ajouter plus de complexité si votre cas d'utilisation l'exige. Par exemple, je n'ai pas du tout de stockage local; parce que mon application peut tolérer la perte de quelques REST réponses.

Mon approche utilise seulement AsyncTasks sous les couvertures. Dans mon cas, j'appelle ces tâches à partir de mon instance Activity; mais pour tenir pleinement compte de cas tels que la rotation d'écran, vous pouvez choisir de les appeler à partir d'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 l'URL réelle REST et le format de données utilisé.

Le client aurait 2 couches:

  1. Couche supérieure: le but de cette couche est de fournir des méthodes reflétant 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).
    Il s'agit du point d'entrée dans l'API client REST. C'est la couche que l'application utiliserait 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 POJO et renvoyée à l'application.

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

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

Assez de texte. Voyons un peu de code maintenant. Prenons une URL hypothétique REST _ API - 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(String userName, final GetResponseCallback callback){
        String restUrl = Utils.constructRestUrlForProfile(userName);
        new GetTask(restUrl, new RestTaskCallback (){
            @Override
            public void onTaskComplete(String 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){
        String restUrl = Utils.constructRestUrlForProfile(profile);
        String requestBody = Utils.serializeProfileAsString(profile);
        new PostTask(restUrl, requestBody, new RestTaskCallback(){
            public void onTaskComplete(String 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. <br/>
     * 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. <br/>
     * This method is guaranteed to execute on the UI thread.
     */
    public abstract void onPostSuccess();

}

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

Ensuite, la couche inférieure (couche AsyncTask) pourrait ressembler à ceci:

/**
 * An AsyncTask implementation for performing GETs on the Hypothetical REST APIs.
 */
public class GetTask extends AsyncTask<String, String, String>{

    private String 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(String restUrl, RestTaskCallback callback){
        this.mRestUrl = restUrl;
        this.mCallback = callback;
    }

    @Override
    protected String doInBackground(String... params) {
        String response = null;
        //Use HTTP Client APIs to make the call.
        //Return the HTTP Response body here.
        return response;
    }

    @Override
    protected void onPostExecute(String result) {
        mCallback.onTaskComplete(result);
        super.onPostExecute(result);
    }
}

    /**
     * An AsyncTask implementation for performing POSTs on the Hypothetical REST APIs.
     */
    public class PostTask extends AsyncTask<String, String, String>{
        private String mRestUrl;
        private RestTaskCallback mCallback;
        private String 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(String restUrl, String requestBody, RestTaskCallback callback){
            this.mRestUrl = restUrl;
            this.mRequestBody = requestBody;
            this.mCallback = callback;
        }

        @Override
        protected String doInBackground(String... arg0) {
            //Use HTTP client API's to do the POST
            //Return response.
        }

        @Override
        protected void onPostExecute(String 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(String result);
    }

Voici comment une application peut utiliser l'API (dans un Activity ou 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 sont suffisants pour expliquer la conception; mais je serais heureux de fournir plus d'informations.

95
curioustechizen

"Développer les applications clientes Android REST" de Virgil Dobjanschi a donné lieu à de nombreuses discussions, aucun code source n'ayant été présenté au cours de la session ou fourni par la suite.

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

Le deuxième lien demande le "meilleur" REST cadre, qui fait l’objet de discussions approfondies sur stackoverflow. Pour moi, la taille de l'application est importante, suivie de la performance de la mise en œuvre.

  • J'utilise normalement l'implémentation plain org.json, qui fait partie de Android depuis le niveau 1 de l'API et n'augmente donc pas la taille de l'application.
  • Pour moi, les informations trouvées sur performances de l'analyseur JSON dans les commentaires sont très intéressantes: à partir de Android 3.0 Honeycomb, l'analyseur de streaming de GSON est inclus sous le nom Android.util.JsonReader. Malheureusement, les commentaires ne sont plus disponibles.
  • Spring Android (que j'utilise parfois) prend en charge Jackson et GSON. Le Spring Android documentation du module 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 utilitaires qui effectuent le mappage (spécifique au projet) et le réseau IO (mon propre modèle REST pour GET ou POST brut). J'essaie d'éviter l'usage de la réflexion.

11
ChrLipp

N'utilisez jamais AsynTask pour effectuer une requête réseau ou quoi que ce soit qui doit être conservé. Les tâches asynchrones sont étroitement liées à votre activité et si l'utilisateur modifie l'orientation de l'écran depuis la création de l'application, la tâche asynchrone sera arrêtée.

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 toute sorte de demande REST de manière asynchrone et de notifier votre interface utilisateur avec Request Listeners implémentant le modèle de service de Virgil Dobjanschi.

7
Pierre Criulanscy

Il existe une autre bibliothèque avec une API beaucoup plus propre et des données de type sûr. 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<Void>() {
        @Override
        public void success(Void ignore, HttpResponse response) {
        }

        @Override
        public void error(String message, HttpResponse response) {
        }

        @Override
        public void failure(NetworkError error) {
        }

        @Override
        public void complete() {
        }
    }).execute();

Il est neuf, mais semble très prometteur.

3
Arthur

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 constater dans la documentation, il est plus simple et plus net que les autres. Ce n'est pas axé sur Android, mais j'utilise et ça marche plutôt bien.

Il supporte HTTP Basic Auth. Il fait le sale boulot de la sérialisation et de la désérialisation des objets JSON. Cela vous plaira, spécialement si votre API s'apparente à Rails.

1
Diego

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 éléments concrets exemples repos pour générer le code client du service REST. Le code remplace les données utiles REST URL et JSON par des méthodes Java et des POJO natifs. Il gère également automatiquement les connexions au serveur, les appels asynchrones et les conversions POJO vers/à partir de JSON.

Notez que cet outil est disponible en différentes versions (cli, plugins, prise en charge d'Android/ios/js) et que vous pouvez utiliser plug-in de studio Android pour générer l'API directement dans votre application.

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

1
Manu