Skip to content

Riflin/marvel

Repository files navigation

Listado de personajes Marvel

Creación de una aplicación de muestra para Entelgy usando el api de Marvel

La aplicación se ha creado usando el patrón Modelo Vista Presentador. Está dividida en tres grandes paquetes: app, con todas las pantallas/diálogos y los presenters, divididos por paquete por pantalla, data, donde están los modelos (divididos a su vez entre personajes, cómics y clases útiles), servicios y providers para acceder a los datos, y domain, con los casos de uso para obtener los datos necesarios.

La aplicación consta de las siguietnes secciones:

  • Listado de personajes
  • Detalles del personaje
  • Detalles del cómic
  • Listado de personajes por cómic
  • PhotoActivity y PhotoListActivity para ver las imágenes a tamaño completo y con posibilidad de hacer zoom
  • WebView para navegar por los diferentes enlaces de cada personaje/cómic sin abrir un navegador externo.

La interfaz de la aplicación se ha hecho siguiendo un poco el diseño de la web de Marvel (diseño de botones, forma de mostrar los personajes en la lista, etc) y usando el rojo marvel como color principal. Quizá queda algo recargada alguna pantalla con tanto rojo, pero al final no se le dedicó un tiempo demasiado grande a hacerla más atractiva visualmente.

Para la instanciación de los presenter se ha creado una clase llamada PresenterFactory, desde donde se obtienen todos los presenter usando el patrón singleton, instanciando un sólo objeto por cada presenter, por lo que la vista no se les puede pasar como parámetro en el constructor y se tiene que inicializar cada vez que obtenemos el presenter en una actividad. Esto se ha hecho así por temas de guardar los datos más allá del ciclo de vida de las actividades, aunque es cierto que en esta aplicación, al no haber navegación compleja ni pantallas con fragments, no aporta mucho y podría haberse instanciado un objeto por cada presenter. De hecho, el presenter de los detalles del cómic se ha hecho así debido a que se puede pasar de un cómic a otro y, en ese caso, al volver atrás la vista se quedaba a null al llamarse el onDestroy(9 del cómic cerrado después de volver al anterior. En este caso sí se instancia un objeto cada vez y se le pasa la vista como parámetro en el constructor. Está detallado también en los comentarios de la aplicación.

Los presenters se encargan de todo, incluida la obtención de los datos pasados a cada activity al crearse. En caso de haber cualquier fallo, se llama al método de la vista (onDataError()) encargado de mostrar un mensaje de error y cerrar la actividad. Las vistas, por su parte, se han creado tontas, y lo único que hacen es tener métodos para ir pintando por pantalla lo que les dice el presenter. En lugar de haber un gran método para mostrar todos los datos de los personajes/cómics, se ha creado un método para cada dato, estando así todo más encapsulado y mantenible, ocupándose cada método de una sola cosa. Las activities heredan todas de una BaseActivity que implementa la interfaz BaseView, de la que heredan todas las vistas. Ahí tenemos unos métodos definidos para ejecutarlos siempre (init(), initViews() y attachListenersToTheViews()), aparte de unos métodos comunes (como el de mostrar un mensaje de error y cerrar la actividad).

Los adapters se han creado con los viewHolder como inner classes dentro de ellos, ya que al linmitarse su uso sólo a ese adapter, he preferido dejarlo así por temas de legibilidad. La única excepción es en la sección de characterdetails, donde un ViewHolder es compartido por cuatro adapters y se ha definido en un paquete viewholder dentro del paquete adapter. Esos cuatro adapters que lo comparten (ComicSummaryAdapter, EventSummaryAdapter, SeriesSummaryAdapter y StorySummaryAdapter) también podrían haberse mejorado, o al menos sus viewHolders, haciendo que los objetos que muestran, que tienen los mismos campos, heredaran de uno superior, pero finalmente se dejaron tal cual sin tocar el modelo. Además, cada uno de los adapters recibe como parámetro un callback para el tipo de dato que muestra, siendo ese callback implementado por el presenter de la sección correspondiente, pudiendo así hacerse cargo de qué hacer cuando se selecciona un objeto del adapter.

Para navegar entre pantallas se ha creado un Routing donde están todos los métodos necesarios para abrir cada pantalla de la aplicación, pasándoles como parámetros los datos necesarios. Cada vez que queramos abrir una ventana deberíamos llamar aquí.

En la sección de characterdetails, cuando se muestran los cómics donde aparece el personaje, tenía pensado crear una nueva pantalla donde ver todos esos cómics (siempre que hubiera más de 20, el límite de cómics mostrados), en una pantalla parecida a la del listado de personajes, pero finalmente no lo implementé para no dilatar aún más la fecha de entrega.

Tanto los cómics como los personajes permiten ver su foto en alta resolución en una nueva actividad (PhotoActivity), y además los comics dan la posibilidad de mostrar un listado de imágenes promocionales del mismo, abriéndose en este caso una nueva activity (PhotoListActivity) con un ViewPager donde se muestran todas. Esto se podría haber juntado todo en una única pantalla, pero primero se creó la PhotoActivity y cuando se creó la PhotoListActivity no se modificó la llamada a la anterior para hacerlo todo en la misma pantalla. Para ampliar las imágenes tenía pensado usar la librería PhotoView, pero no la descargaba el gradle por alguna razón y nos decidimos por ZoomageView como sustituta.

Por último, cada vez que pulsamos en un enlace de los que tienen los cómics y los personajes, se abrirá un webView personalizado, con un progress personalizado también para mostrarlo cuando se va cargando la página. De esta forma nos evitamos tener que abandonar la aplicación para abrir un navegador externo.

Como colofón, se ha creado también un CustomProgressBar para usarlo en la aplicación cada vez que estamos cargando algo, así como un DialogInformacion para mostrarlo cuando haya que avisar de cualquier cosa al usuario.

Dentro del modelo de datos, también dividido entre objetos para los comics y los personajes, se ha creado un paquete utils donde se han guardado unas clases (dos enum, en este caso) utilizadas para facilitar el trabajo con la app.

Las llamadas a la api se han definido en dos interfaces donde están los métodos usados en la aplicación para descargar información del servidor. A estas llamadas hay que pasarles siempre una serie de datos para que la api de marvel funcione correctamente, lo que se ha hecho con un interceptor usado al crear el objeto Retrofit y que se encarga de añadirle esos parámetros a todas las llamadas que hagamos. También se ha usado un Deserializer propio para la deserialización de las fechas al crear los objetos. Cada llamada devuelve un objeto response que nos indica si la llamada ha sido satisfactoria o no. Pensé en hacer estas llamadas con observables, pero finalmente me decidí por este método y las corutinas para hacer las llamadas en segundo plano.

Por último, los useCase heredan todos de un NetworkUseCase padre parametrizado, que tiene un método downloadData que devuelve un response con el tipo de dato que estemos descargando

About

Marvel app for Entelgy

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages