SplashScreen que act煤a de forma din谩mica si empleamos un dispositivo o emulador a partir de la API 31 y de forma est谩tica con el resto. La documentaci贸n para su implementaci贸n la encontramos aqu铆.
Marvel App
馃Phone Demo
Descripci贸n
Aplicaci贸n Android desarrollada en Kotlin siguiendo el patr贸n de dise帽o MVVM, resultado de la pr谩ctica final del m贸dulo Android Superpoderes del Bootcamp de Desarrollo de Apps M贸viles de KeepCoding, que destaca por su uso de Jetpack Compose para la creaci贸n de una interfaz de usuario din谩mica y reactiva.
Con un listado de superh茅roes y una pantalla de detalle para cada uno, los usuarios pueden explorar informaci贸n detallada sobre sus personajes favoritos, adem谩s de disfrutar de una experiencia fluida y receptiva gracias a la programaci贸n reactiva implementada con Kotlin Flow y corrutinas. La integraci贸n de tecnolog铆as como Room para el almacenamiento local y Retrofit para las comunicaciones con el backend garantiza una eficiencia 贸ptima, mientras que la adhesi贸n a los principios de CLEAN y SOLID asegura la escalabilidad y mantenibilidad del c贸digo. Adem谩s, la aplicaci贸n se somete a testing, que incluye pruebas unitarias, mocks, fakes y tests de UI, para garantizar su estabilidad y calidad en todo momento.
鈿狅笍 Informaci贸n mucho m谩s detallada en el README del proyecto en GitHub. 鈿狅笍
Caracter铆sticas y funcionalidades
- Arquitectura CLEAN.
- Model-View-ViewModel (MVVM).
- Jetpack Compose
- SplashScreen API
- Consumo de API Rest con Retrofit y la biblioteca OkHttp.
- Corrutinas.
- Kotlin Flow.
- Room.
- Inyecci贸n de dependencias con Dagger Hilt.
- Unit Testing y UI Testing.
La pantalla principal de la aplicaci贸n utiliza un Scaffold
para organizar componentes de uso general. En este caso, la TopAppBar
se emplea para mostrar una imagen del logo de Marvel.
Por otra parte, se implementa un LazyColumn
que posee como primer item un LazyRow
que se encarga de contener a los personajes que han sido marcados como favoritos (acci贸n que se realiza de forma reactiva empleando un stream de Kotlin Flow conectado con nuestra base de datos en Room que env铆a los modelos de datos correspondientes a los personajes almacenados, por lo que, en primer lugar, se actualiza el estado de favorito del superh茅roe a nivel local y, reactivamente, la interfaz).
Como se observa en la imagen, en el caso de que no haya ning煤n personaje seleccionado como favorito, se muestra el composable pertinente que avisa al usuario de que todav铆a no hay superh茅roes favoritos guardados.
El resto de items de la LazyColumn
se corresponde con el listado de personajes que obtenemos de la Marvel API.
Cabe se帽alar que cada llamada a la API de Marvel est谩 limitada para obtener solamente veinte personajes, por lo que si queremos obtener m谩s superh茅roes, tenemos que gestionar m谩s llamadas a la API cuando el usuario alcance el final de la lista actual. De esta forma, gracias a la gesti贸n del estado de la vista con una Sealed Class
y a la detecci贸n de la posici贸n actual del scroll del usuario en la LazyColumn
, se maneja la paginaci贸n y la obtenci贸n de m谩s personajes.
Como vemos en la imagen, se muestra un CircularProgressIndicator
mientras se realiza la llamada a la API en un hilo secundario.
Aqu铆 se ve c贸mo ser铆a la pantalla con personajes marcados como favoritos, as铆 como el IconButton
empleado para contener un coraz贸n que cambia seg煤n el estado de favorito del superh茅roe.
Como ya se ha mencionado, el listado de personajes se actualiza reactivamente gracias a la conexi贸n con Room a trav茅s de un stream de Kotlin Flow, el cual proporciona, uno a uno, el modelo de datos de cada superh茅roe siempre que haya cambios en nuestra base de datos local.
Detalle del personaje una vez que se ha hecho click sobre 茅l en el listado de la pantalla principal.
Con un Scaffold
se ha incluido una TopAppBar
que contiene un IconButton
para volver a la pantalla principal y un texto que enuncia la secci贸n en la que nos encontramos. El resto de la screen se corresponde con un LazyColumn
con cuatro items: el primero para la foto del personaje y su nombre, el segundo para la descripci贸n del superh茅roe, el tercero para un LazyRow
contenedor de los comics en los que aparece el personaje y un cuarto para otro LazyRow
que contiene las series.
Todos estos datos son obtenidos o desde local (nombre y foto del personaje, por ejemplo) o desde remoto (listado de comics y series, por ejemplo), por lo que, en este 煤ltimo caso, puede que la informaci贸n no la tengamos de inmediato, as铆 que en pos de atender a la experiencia de usuario, es id贸neo agregar alguna se帽al de que se est谩 a la espera de obtener ciertos datos. En este caso, se ha incluido el denominado efecto Shimmer mientras se est谩n cargando los datos referidos a los comics y las series.
Una de mis preocupaciones fue la de ir acumulando memoria cada vez que se cargaban m谩s y m谩s personajes en local, persistiendo demasiados datos que, llegado el momento, pudieran afectar al rendimiento de nuestra aplicaci贸n y, por ende, la experiencia de usuario. De esta forma, pens茅 en implementar una limpieza de datos de local cada vez que el usuario abandonara la aplicaci贸n realizando el tradicional onBackPressed
, el cual se gestiona de manera m谩s f谩cil en Jetpack Compose con el BackHandler
.
As铆, pude gestionar, que al salir de esta forma, se mostrase un Dialog
y que, al confirmar la salida, se eliminasen todos los personajes de base de datos excepto los 20 primeros.
Es evidente que tambi茅n se eliminar谩n los favoritos que estuvieran guardados entre esos personajes eliminados, cosa que se solucionar铆a f谩cilmente almacen谩ndolos de forma separada al resto, pero para m铆 el objetivo era aprender a gestionar el onBackPressed
y a atender a la eficiencia de la memoria al largo plazo del uso de la aplicaci贸n.