Proyecto Usuarios con Arquitectura

Descargar estos ejercicios

Ejercicio

Para crear nuestro primer proyecto siguiendo la arquitectura explicada en los apuntes, vamos a realizar un ejercicio guiado que posteriormente ampliaremos. La app va a seguir siendo de CONSOLA de Kotlin, y tratará de gestionar la entrada a una aplicación mediante las típicas opciones para logearse. Para partir de la misma base y que sea más sencillo el seguimiento de este ejercicio, lo primero que haremos será renombrar el paquete a arquitectura_usuario

1. Creando el paquete data

Vamos a comenzar creando los elementos necesarios para la manipulación de los datos, paquete data. Como ya hemos visto en el tema, el paquete data lo crearemos directamente dentro del paquete base arquitectura_usuario.

Como todavía no tenemos conocimiento de acceso a BD con Android, vamos a usar la simulación de esta mediante colecciones, y como ya se ha explicado en el tema, la simulación se creará dentro del paquete mocks de data, por lo que el siguiente paso será crear el paquete mocks dentro del paquete data:

  1. En un archivo nuevo llamado UsuarioMock.kt se creará la data class UsuarioMock, con las propiedades inmutables login y password de tipo String.

  2. En un archivo nuevo llamado UsuarioDaoMock.kt se creará laClase UsuarioDaoMock, clase en la que crearemos una lista mutable con los usuarios para pruebas y a la que además le añadiremos los métodos que nos permitan manipular estos datos:

    get(): MutableList<UsuarioMock>
    get(login: String): UsuarioMock? 
    insert(usuarioRemoto: UsuarioMock)
    update(usuarioRemoto: UsuarioMock)
    delete(login: String)
    

💡 Tips: En la siguiente imagen puedes ver la estructura de carpetas afectada hasta el momento.

Project[.gradle][.idea][app][build][src][src][kotlin][arquitectura_usuarios][data][mock][usuario]UsuarioMock.ktUsuarioDaoMock.kt[views]MainApp.kt[build][gradle]...

2. Creamos el paquete models

Como hemos visto en el tema, para cumplir con la arquitectura de capas propuesta, deberemos tener las clases Modelo necesarias que independicen las fuentes de datos de la lógica de la aplicación, por lo que deberemos crear el paquete models (que situaremos a nivel de data cumpliendo la arquitectura propuesta), dentro de este paquete se creará la data class Usuario correspondiente a UsuarioMock y que en un principio tendrá las mismas propiedades que esta última.

3. Creando el repositorio en el paquete data

Volvemos a data y deberemos crear las clases Repositorio que nos hagan de puente entre los Mocks y los Modelos, en nuestro caso solo tenemos UsuarioMock y el tipo modelo correspondiente Usuario. Por lo que deberemos hacer lo siguiente:

  1. Crearemos el archivo UsuarioRepository.kt dentro del paquete data, con la clase UsuarioRepository que tendrá una propiedad inmutable de tipo UsuarioDaoMock a través de la cual podremos acceder a los métodos de esta clase. Para ello crearemos los métodos paralelos a los de la clase DAO, pero esta vez los datos de entrada y salida serán de tipo Usuario. Por ejemplo, tendremos el siguiente método en UsuarioRepository:

        fun get():List<Usuario> = proveedorUsuarios.get().toUsuarios()
    
  2. También dentro de data crearemos el archivo RepositoryConverter.kt en el que incluiremos todos los métodos que sirven para mapear ente Usuario y UsuarioMock, como se ha explicado en el punto 3 de estructurando la capa de datos del tema 2.3 de Arquitectura.

💡 Tips: Los anteriores elementos habrán quedado como en la siguiente imagen:

Project...[arquitectura_usuarios][data][mock][usuario]UsuarioMock.ktUsuarioDaoMock.ktUsuarioRepository.ktUsuarioRepositoryConverter.kt[models]Usuario.kt[views]MainApp.kt...

4. Definiendo el paquete ui.features

Para hacer posible la lógica del programa sin usar las clases de Android (recuerda que estamos en una aplicación de consola), vamos a utilizar una serie de funciones y propiedades que en un caso real no serían necesarias.

Por tanto, dentro de UsuarioScreen.kt crearemos la función

i. mostrarInformacion a la que le llegará la lista de usuarios y mostrará la salida por pantalla, esta función será llamada desde el evento correspondiente gestionado en UsuarioViewModel.
ii. actualizaEstado a la que le llega estadoUsuarioUiState: UsuarioUiState y se encargará de actualizar una variable global de este archivo y que nos servirá para controlar si se ha logeado el usuario correctamente, a esta función la llamaremos desde la clase UsuarioViewModel en cada interacción con los eventos (de forma que utilizaremos la propiedad usuarioUiState del ViewModel para actualizar esta variable). Esto lo haremos porque la aplicación mostrará un mensaje antes de la salida del menú, indicando que el usuario está logeado o no lo está. Solo podremos cambiar la contraseña de un usuario logeado.

Usted no está logeado
1. Sign in
2. Login
...
1. Sign in
2. Login
3. Change password
4. Logout
5. List
6. Exit
2
Introduce login pepe
Introduce la contraseña pepe12  
Usuario: pepe logeado
1. Sign in
2. Login

5. Definiendo el paquete views

En este paquete solo tendremos la función main que contendrá una variable inmutable de tipo viewModel y realizará la llamada a la función usuarioScreen. De la siguiente manera:

val usuarioViewModel = UsuarioViewModel()
usuarioScreen(usuarioViewModel::onUsuarioEvent)

💡 Tips: Al final la arquitectura te habrá quedado como la siguiente, resaltados los últimos elementos añadidos:

Project...[arquitectura_usuarios][data][mock][usuario]UsuarioMock.ktUsuarioDaoMock.ktUsuarioRepository.ktUsuarioRepositoryConverter.kt[models]Usuario.kt[ui.features][usuario][UsuarioUiState.kt][UsuariEvent.kt][UsuarioViewModel.kt][UsuariScreen.kt][views]MainApp.kt...