Android REST cliente, ¿muestra?

Incluso si este hilo ha aceptado una respuesta, siéntase libre de proponer otras ideas, use o le guste


Conocí estos artículos:

  • Servicio de API relajante
  • API de cliente REST de Java para Android

Y eso me llevó a este video de Google I / O 2010 sobre las aplicaciones cliente REST

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

Desde ahora, he estado creando un componente REST como componente estático en mi clase de controlador de aplicaciones.

A partir de ahora, creo, debería cambiar el patrón. Alguien señaló que la aplicación Google IOSched es una gran muestra de cómo escribir clientes REST en Android. Alguien más dijo que esta manera es demasiado complicada.

Entonces, ¿alguien puede mostrarnos cuál es la mejor práctica? De manera corta y simple.
La aplicación IOSched es demasiado compleja para el caso de uso de muestra.

EDICION 2 (octubre de 2017):

Es 2017. Solo usa Retrofit. No hay casi ninguna razón para usar cualquier otra cosa.

EDITAR:

La respuesta original tiene más de un año y medio de antigüedad en el momento de esta edición. Aunque los conceptos presentados en la respuesta original aún se mantienen, como lo señalan otras respuestas, ahora hay bibliotecas que hacen que esta tarea sea más fácil para usted. Más importante aún, algunas de estas bibliotecas manejan los cambios de configuración del dispositivo por usted.

La respuesta original se conserva a continuación para referencia. Pero, por favor, también tómese el tiempo para examinar algunas de las bibliotecas del cliente Rest para Android para ver si se ajustan a sus casos de uso. La siguiente es una lista de algunas de las bibliotecas que he evaluado. De ninguna manera pretende ser una lista exhaustiva.

  • Volley (esto es de Google)
  • RESTDroid
  • RoboSpice
  • Adaptación

Respuesta Original:

Presentar mi enfoque para tener clientes REST en Android. No afirmo que sea el mejor sin embargo 🙂 Además, tenga en cuenta que esto es lo que se me ocurrió en respuesta a mi requerimiento. Es posible que necesite tener más capas / agregar más complejidad si su caso de uso lo exige. Por ejemplo, no tengo almacenamiento local; porque mi aplicación puede tolerar la pérdida de algunas respuestas REST.

Mi enfoque usa solo AsyncTask s debajo de las cobijas. En mi caso, “llamo” estas Tareas desde mi instancia de Activity ; pero para tener en cuenta completamente casos como la rotación de pantalla, puede optar por llamarlos desde un Service o similar.

Yo conscientemente elegí mi cliente REST para ser una API. Esto significa que la aplicación que utiliza mi cliente REST ni siquiera necesita conocer las URL REST reales y el formato de datos utilizado.

El cliente tendría 2 capas:

  1. Capa superior: el objective de esta capa es proporcionar métodos que reflejen la funcionalidad de la API REST. Por ejemplo, podría tener un método Java correspondiente a cada URL en su API REST (o incluso dos: una para GET y una para POST).
    Este es el punto de entrada a la API del cliente REST. Esta es la capa que la aplicación usaría normalmente. Podría ser un singleton, pero no necesariamente.
    La respuesta de la llamada REST es analizada por esta capa en un POJO y devuelta a la aplicación.

  2. Esta es la capa AsyncTask nivel inferior, que usa métodos de cliente HTTP para salir y realizar esa llamada REST.

Además, elegí usar un mecanismo de callback para comunicar el resultado de la AsyncTask a la aplicación.

Suficiente de texto. Veamos algunos códigos ahora. Tomemos una hipotética URL REST API – http://myhypotheticalapi.com/user/profile

La capa superior puede verse así:

  /** * 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. 
* 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(); }

Tenga en cuenta que la aplicación no utiliza el JSON o XML (o cualquier otro formato) devuelto por la API REST directamente. En cambio, la aplicación solo ve el Profile bean.

Entonces, la capa inferior (capa AsyncTask) podría verse así:

 /** * An AsyncTask implementation for performing GETs on the Hypothetical REST APIs. */ public class GetTask extends AsyncTask{ 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{ 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); } 

Así es como una aplicación puede usar la API (en una Activity o 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 } }); 

Espero que los comentarios sean suficientes para explicar el diseño; pero me gustaría proporcionar más información.

“Desarrollo de aplicaciones de cliente REST de Android” por Virgil Dobjanschi condujo a mucha discusión, ya que no se presentó ningún código fuente durante la sesión o se proporcionó después.

La única implementación de referencia que conozco (por favor comente si sabe más) está disponible en DataDroid (la sesión de Google IO se menciona en / presentation). Es una biblioteca que puedes usar en tu propia aplicación.

El segundo enlace solicita el “mejor” marco REST, que se analiza ampliamente en stackoverflow. Para mí, el tamaño de la aplicación es importante, seguido del rendimiento de la implementación.

  • Normalmente uso la implementación plain org.json, que es parte de Android desde el nivel 1 de la API y, por lo tanto, no aumenta el tamaño de la aplicación.
  • Para mí, fue muy interesante la información encontrada en el rendimiento de los analizadores JSON en los comentarios: a partir de Android 3.0 Honeycomb, el analizador de transmisión de GSON se incluye como android.util.JsonReader. Lamentablemente, los comentarios ya no están disponibles.
  • Spring Android (que uso a veces) es compatible con Jackson y GSON. La documentación del módulo Spring Spring RestTemplate apunta a una aplicación de muestra .

Por lo tanto, me apego a org.json o GSON para escenarios complejos. Para la architecture de una implementación de org.json, estoy usando una clase estática que representa los casos de uso del servidor (por ejemplo, findPerson, getPerson). Llamo a esta funcionalidad de un servicio y uso las clases de utilidad que están haciendo el mapeo (específico del proyecto) y el IO de la red (mi propia plantilla REST para GET simple o POST). Intento evitar el uso de la reflexión.

Nunca use AsynTask para realizar una solicitud de red o lo que sea que deba persistir. La tarea asincrónica está fuertemente ligada a su actividad y si el usuario cambia la orientación de la pantalla desde que se creó la aplicación, la tarea AsyncTask se detendrá.

Le sugiero que use el patrón de servicio con el servicio de atención y el receptor de resultados. Eche un vistazo a RESTDroid . Es una biblioteca que le permite realizar cualquier tipo de solicitud REST de forma asincrónica y notificar a su UI con los solicitantes de audiencia que implementan el patrón de servicio de Virgil Dobjanschi.

Hay otra biblioteca con API mucho más limpia y datos seguros para el tipo. https://github.com/kodart/Httpzoid

Aquí hay un ejemplo de uso simple

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

O más complejo con devoluciones de llamadas

 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(String message, HttpResponse response) { } @Override public void failure(NetworkError error) { } @Override public void complete() { } }).execute(); 

Es nuevo, pero parece muy prometedor.

Hay muchas bibliotecas y estoy usando esta: https://github.com/nerde/rest-resource . Esto fue creado por mí, y, como puede ver en la documentación, es mucho más limpio y simple que los otros. No está enfocado en Android, pero lo estoy usando y está funcionando bastante bien.

Es compatible con HTTP Basic Auth. Hace el trabajo sucio de serializar y deserializar objetos JSON. Te gustará, especialmente si tu API es como Rails.

Descargo de responsabilidad: estoy involucrado en el proyecto de código abierto rest2mobile

Otra alternativa como cliente REST es usar rest2mobile .

El enfoque es ligeramente diferente ya que utiliza ejemplos de descanso concretos para generar el código de cliente para el servicio REST. El código reemplaza las URL de REST y las cargas de JSON con los métodos de Java nativos y los POJO. También maneja automáticamente conexiones de servidor, invocaciones asíncronas y POJO a / desde conversiones JSON.

Tenga en cuenta que esta herramienta viene en diferentes sabores (cli, plugins, android / ios / js) y puede usar el plugin de android studio para generar la API directamente en su aplicación.

Todo el código se puede encontrar en github aquí .