Para construir una aplicación de alta calidad, hay que prestar mucha atención a la arquitectura de la app, ya que su papel es decisivo. De hecho, las decisiones más fundamentales que determinan la estructura y la interacción de los componentes dependen de la arquitectura. Por lo tanto, elegir la arquitectura adecuada es uno de los puntos clave para construir un producto decente. Para que la aplicación sea fiable, escalable y fácilmente comprobable, es necesario desde el principio del desarrollo establecer los principios de su funcionamiento. Esto ayuda a eliminar la interconexión rígida de los elementos, a facilitar la lectura y la modificación del código y a garantizar un equilibrio entre la calidad y la velocidad de desarrollo.

En el artículo que presentamos a los lectores, tratamos de considerar una de las opciones para implementar una arquitectura de alta calidad utilizando la pila de Kotlin (lenguaje de desarrollo), MVVM (lógica de interacción de los componentes de la aplicación), Koin (inyección de dependencias) y coroutines (multihilo). ¿Por qué esta pila? Kotlin es el lenguaje oficialmente recomendado por Google para el desarrollo de Android. En comparación con Java, elimina un gran número de boilerplate, tiene un beneficioso enfoque de seguridad nula, clases de datos, etc. MVVM (Model-View-ViewModel) – un patrón arquitectónico que permite separar la UI, la lógica de negocio y las fuentes de datos. Koin es una biblioteca ligera con un conjunto de funciones convenientes para implementar la idea de inyección de dependencia. Facilita la creación de singletons, la creación de ámbitos personalizados y la inyección de dependencias. Por último, las coroutines son una característica interesante de Kotlin para el multihilo. Pueden considerarse como flujos ligeros, cuya creación no requiere muchos recursos.

Nuestra aplicación de prueba se llamará “Explorador de perros” y mostrará una lista de diferentes razas de perros. Sacaremos los datos del recurso https://api.thedogapi.com/

En primer lugar, cree un nuevo proyecto en el IDE de Android Studio. Entre las plantillas propuestas, seleccione la Actividad vacía. El lenguaje de desarrollo es Kotlin; el nivel mínimo de la API es 21 (Android 5); usar artefactos androidx es verdadero.

Conecte las dependencias necesarias para el proyecto. En primer lugar, añada la biblioteca Koin. En el archivo build.gradle (módulo de la aplicación), inserte las siguientes líneas:

La variable $koin_version se guarda en el build.gradle de todo el proyecto. Después de ext.kotlin_version, añada la línea ext.koin_version = ‘2.0.1’. Tenga en cuenta que el proyecto utiliza la segunda versión de Koin.

Para las peticiones al servidor, utilizaremos las bibliotecas OkHttp y Retrofit 2. Por el mismo principio, añada a build.gradle (módulo de la aplicación)

y en el build.gradle de todo el proyecto

Sincronizamos los archivos de Gradle.

Ahora podemos preparar las primeras inyecciones. En Koin, el objeto proveedor es la clase Module, creada mediante una función con el inesperado nombre module(). Para crearla, utilizamos la maravillosa capacidad de Kotlin: funciones y variables a nivel de paquete. A diferencia de Java, Kotlin permite almacenar funciones y variables no sólo en clases, sino también en archivos. En términos de significado, esto es similar a las clases de utilidad estáticas en Java, pero mucho más conveniente. En el paquete dogexplorer, cree un nuevo paquete di, y en él el archivo appModule. En el archivo, cree un objeto de clase Módulo

Los nombres del archivo y de la variable no tienen por qué coincidir. En nuestro proyecto, esto se hace por conveniencia y comprensibilidad.

Para trabajar con la red, necesitamos 3 clases: OkHttpClient (para las peticiones propiamente dichas), Retrofit (para convertir convenientemente nuestros objetos a JSON y viceversa) y la interfaz NetworkApi (en la que definimos las peticiones al servidor).

Cree 3 funciones. La primera devolverá una instancia de OkHttpClient con el interceptor de registro conectado, algo ventajoso para controlar los datos que se envían y reciben.

El segundo crea una instancia de Retrofit. Especificamos Gson como convertidor de nuestros objetos a JSON y viceversa, CoroutineCallAdapter para envolver las respuestas del servidor en coroutines para la asincronía. La URL base, por comodidad, se puede convertir en constantes. Para ello, creamos el paquete utils dentro del paquete dogexplorer, luego dentro de él, creamos el archivo constants.kt, en el que añadimos la línea val baseUrl =“https://api.thedogapi.com/v1/”.

La tercera función debería tener el siguiente aspecto

Como aún no hemos creado la interfaz, la añadiremos al proyecto. Creamos el paquete modelo y dentro de él NetworkApi. Tenga en cuenta que no debe añadir un archivo o clase Kotlin, sino una interfaz.

Dado que no necesitamos crear una nueva instancia de NetworkApi cada vez que la añadimos al ViewModel, utilizaremos la función única para crear singletons. Cambie la función appModule () para que tenga el siguiente aspecto:

Para que la NetworkApi empiece a beneficiarse, definiremos en ella métodos para obtener una lista de razas de perros y para obtener imágenes. Antes de escribir los métodos, es aconsejable familiarizarse con la documentación de nuestro backend. Puede encontrarla en https://docs.thedogapi.com/. Como puede ver, el servidor requerirá una clave API para cada solicitud. Por lo tanto, en primer lugar, debemos obtenerlas rellenando un sencillo formulario a partir del correo electrónico y la descripción de nuestra solicitud en la página https://thedogapi.com/signup. El correo electrónico con la clave generada del tipo de cadena “580e40f4-4144-8d75-a8fb-89a822a3126f” se enviará al correo electrónico que haya especificado (¡Atención! Se trata de una clave no válida, sólo como ejemplo). Guarde su clave en el archivo constants.kt como una variable

El método getBreeds () nos devolverá una lista de razas de perros. En primer lugar, es necesario crear una clase envolvente en la que la biblioteca Gson convertirá la respuesta del servidor. Puede crearla manualmente creando una clase y definiendo los atributos adecuados para ella. La lista de campos necesarios se encuentra en https://docs.thedogapi.com/api-reference/models/breed.

Sin embargo, recomendamos encarecidamente el segundo método, que es mucho más productivo. Añada el plugin JSON To Kotlin Class a Android Studio. Para ello, vaya al menú de búsqueda de plugins abierto Archivo / Configuración / Plugins. En el campo de búsqueda, introduzca el nombre deseado, instale el plugin y reinicie el IDE.

A continuación, en el paquete de modelos, añada el paquete de nuevas entidades. Llamamos al menú contextual con el botón derecho del ratón y entre las opciones del nuevo elemento, seleccionamos Kotlin Data Class File from JSON. Este plugin permite generar clases de datos Kotlin a partir de una muestra JSON. Puede obtener una respuesta de ejemplo en https://docs.thedogapi.com/api-reference/breeds/breeds-list, enviando una solicitud de prueba. Copiamos la respuesta recibida en el campo de entrada del plugin, indicamos el nombre de la clase de raza y hacemos clic en Generar. El plugin creará 3 fechas de clase: Raza, Altura y Peso. Las clases de fechas en Kotlin proporcionan una práctica funcionalidad para crear las llamadas clases POJO, diseñadas únicamente para el almacenamiento de datos. Generarán automáticamente las funciones equals (), hashCode () y copy (), setters y getters para cada atributo. El código es muy conciso, pero eficaz.

Habiendo recibido una clase envolvente, podemos terminar de escribir una función para obtener una lista de razas. Hay dos opciones para su implementación. La primera es añadir un modificador de suspensión que permita pausar la función. La segunda opción es envolver la llamada en la interfaz Deferred, que es un futuro cancelable no bloqueante. En este caso, la llamada es más concisa. Detengámonos en ello.

Una anotación sobre la función significa que nuestra aplicación hará una petición get al endpoint base URL + razas. Para simplificar, pasamos la cabecera como parámetro de la petición. En aplicaciones más complejas, es aconsejable añadirlo a un interceptor de autenticidad separado.

La funcionalidad para trabajar con la red está prácticamente completa. Ahora retomamos la implementación del enfoque MVVM. Si no está familiarizado con él, le recomendamos que lea el artículo de Hazem Saleh.

En primer lugar, vamos a racionalizar nuestro proyecto. En el paquete dogexplorer, cree el paquete UI, que, a su vez, el paquete main. Transferimos MainActivity a este paquete. Aquí creamos una nueva clase MainViewModel, que extiende el ViewModel. Para que funcione, necesita networkApi (para solicitar datos al servidor), coroutineScope (para gestionar las coroutines) y LiveData para transferir datos a la Activity. Dispatchers.IO en el constructor de CoroutineScope significa que utilizamos el grupo de hilos recomendado para las operaciones de E/S con un límite de 64 o más (si el dispositivo tiene un procesador con más de 64 núcleos).

Añade una función para obtener una lista de razas. En nuestro coroutineScope, creamos una nueva coroutina con el constructor de coroutinas de lanzamiento. Aquí, obtenemos una lista de razas del servidor y la enviamos a LiveData.

También añadimos la cancelación de la coroutina en la función onCleared () de nuestro MainViewModel. Al destruir el MainViewModel, se detendrán las coroutines que se estén ejecutando en su coroutineScope.

Ahora tenemos que añadir MainViewModel a MainActivity. En el paquete di, cree un archivo separado viewModelModule.kt. En él definimos la variable viewModelModule. También podríamos añadirla en el archivo appModule.kt, pero con el ejemplo siguiente quedará más claro. Esta vez inyectamos la dependencia utilizando un método especial viewModel (), que permite inyectar descendientes de ViewModel en una Actividad o Fragmento.

Para obtener un enlace a MainViewModel, sólo tenemos que añadir una línea a MainActivity.

Para que nuestras inyecciones funcionen, necesitamos iniciar la biblioteca Koin. Esto ocurre cuando se inicia la aplicación. Para ello, cree una clase App que extienda a Application, y añada código a su método onCreate (). No olvide registrar la nueva clase en el manifiesto de la aplicación.

El toque final – mostramos los resultados de la solicitud al servidor en la pantalla de nuestra aplicación. En primer lugar, añada una nueva dependencia en build.gradle (módulo de la aplicación). Sincronice gradle.

Cambia el diseño de la pantalla principal añadiendo un RecyclerView.

En el paquete res/layout, añada el diseño del elemento de la lista de nuestro RecyclerView llamado dog_item.xml. Es lo más sencillo posible y mostrará el nombre de la raza.

Cree un adaptador para RecyclerView.

Por último, podemos consultar los datos y mostrarlos en el DogAdapter. Para ello, añada el código en el método onCreate MainActivity

Ahora podemos lanzar nuestro proyecto e irradiar orgullo ya que acabamos de dominar una nueva pila de desarrollo Android.

Vea cómo desarrollamos una soluciónpara una logística de fitnessclara utilizandoKotlin como tecnología principal

Este campo es obligatorio.

See how we developed a solution for clear-cut fitness logistics using Kotlin as a core technology