Usando APIs (II)

Explicando las clases a usar

Cómo ya hemos dicho, todo el proceso se realizará dentro de los métodos de las AsyncTasks. Ello, empero, no implica que en dichas clases nos encontremos un tocho de código enorme y de difícil mantenimiento, por lo que dividiremos el proceso en trozos que encapsularemos en diferentes clases.

Una API normalmente tiene mas de una funcionalidad, cada una con su petición diferente (diferentes urls, diferentes parámetros, etc.). Pongamos por ejemplo la API de geocoding. Nos permite tanto recibir datos con los que formar la dirección de un par de coordenadas dadas como recibir las coordenadas de una dirección dada. Ambas peticiones van a la misma url, variando sólo las variables que se suministran. Podemos, por tanto, considerar que son dos métodos diferentes de una misma petición, creando así una clase para encapsular los métodos necesarios como GeocodingRequest.

Esta clase se encarga de obtener (y devolver) los datos que suministran la API como una String en formato JSON. Obviamente necesitaremos extraer los datos y encapsularlos en objetos de acceso a datos (DAO, que ya sabemos lo esclavos del anglosajón que somos en las TIC), y para ello necesitaremos un Parser o analizador. Tanto para datos en formato JSON como para los que recibamos (no en este caso, pero es otra opción de las APIs) en XML, la estructura de datos la marca quién diseñó el API, por lo que los Parsers hay que hacerlos “a medida”. Un único Parser puede hacerse cargo de convertir en DAOs los datos de todas las peticiones de una misma API, aunque por facilitar el mantenimiento yo recomendaría hacer una clase de parsing para cada clase Request que tengamos. Para este caso, hemos creado la clase AddressParser, que también podría incluir un método para el JSON que recibiéramos por enviar una dirección esperando recibir coordenadas. El objeto DAO que devuelve, GoogleGeocodeAddressDAO, está formado a su vez por otros objetos (al codificarlo intenté dejarlo todo preparado por si quería mas adelante ampliar funcionalidad) los cuales pueden verse aquí.

Ahora supongamos – si bien no es ése el caso – que tenemos varios objetos Request. Podríamos dejar que las diferentes AsyncTasks llamaran cada cual a los suyos y, con los String resultantes, llamaran a los Parsers para montar los DAO, pero queda todo mas ordenado y controlado si hacemos que sea una única clase, una gestora de comunicaciones, la que haga esas llamadas y devuelva un objeto de respuesta genérico que incluya no sólo el DAO sino también información sobre si el proceso ha ido bien o mal y, en caso de ir mal, en qué ha fallado. Creé para dicha respuesta genérica la clase ResponseEnvelope, la cual tiene el estado del proceso (OK o KO), el mensaje de error (en qué ha fallado el proceso) y un objeto de tipo AbstractDAO del que heredan todos los objetos DAO. Dado que AbstractDAO no añade nada nuevo a los descendientes, bien podría ser una Interfaz. Funcionarían igual (la diferencia principal estribaría en usar implements en vez de extends), por lo que, salvo purismos, es una cuestión de gustos. Para ello, la clase CommManager nos permite centralizar todas las llamadas. En sus métodos se llama a las Requests para obtener los JSON (o XML si fuera el caso) que se pasan a los Parsers para que devuelvan el DAO correspondiente. Todo ello tomando nota de cualquier problema (léase excepción) para que quede reflejado en la ResponseEnvelope. Para ello, todos los métodos susceptibles de excepción las lanzan, es en los métodos del CommManager dónde se atrapan y gestionan convenientemente.

Nota: Se puede observar que tanto ResponseEnvelope como AbstractDAO están empaquetadas fuera de los paquetes de las API geocoding y urlshortening. Esto es así porque ambos paquetes emplean el mismo esquema y quise evitar clases redundantes.

Listo todo esto, sólo necesitamos preparar las AsyncTasks. Dependiendo de si los parámetros que se pasan a los diferentes métodos de una misma Request son compatibles o no será posible que una misma AsyncTask se haga cargo de todos los métodos de dicha Request. En caso negativo, tocaría hacer una AsyncTask para cada funcionalidad implementada, aún cuándo varias estuvieran en una misma clase Request. En nuestro caso, la AsyncTask para el Geocoding Inverso (convertir coordenadas en una dirección) sería la ReverseGeocodingAsyncTask. La clase tiene un atributo listener del tipo de la interfaz Listener que hayamos creado (en nuestro caso, ReverseGeocodingListener) que ha de tener un método al cual se le pase un objeto ResponseEnvelope. La AsyncTask, además, debe tener un método para “setear” el listener, así como implementar al menos los métodos doInBackground, que será el que llame al método adecuado del CommManager, y onPostExecute, que se encargará de notificar que se ha terminado el proceso llamando al método de la interfaz Listener.

Las clases para el acortamiento de url son muy similares, variando quizá en detalles intrínsecos de la propia API. Al igual que las de geocoding no implementan todas las funcionalidades ofrecidas por la API, pero sí permiten enviar una url “larga” y recibir una corta.

En el próximo artículo veremos una pequeña app para ver cómo se usan estas clases.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: