Proyecto: App de Forage

1. Antes de comenzar

En este codelab, se presenta una nueva app llamada Forage, que compilarás por tu cuenta. En él, seguirás los pasos necesarios para completar el proyecto de la app de Forage, incluidas la configuración y las pruebas en Android Studio.

Requisitos previos

  • Este proyecto está destinado para quienes completaron la unidad 5 del curso de Aspectos básicos de Android en Kotlin.

Qué compilarás

  • Agregarás persistencia con Room a una app existente implementando una entidad, un DAO, un ViewModel y una clase de base de datos.

Requisitos

  • Una computadora que tenga Android Studio instalado

2. Descripción general de la app finalizada

La app de Forage completa permite que los usuarios realicen un seguimiento de los artículos, como los alimentos, que buscaron en la naturaleza. Estos datos se conservan entre sesiones mediante Room. Usarás tus conocimientos sobre Room y realizarás operaciones de lectura, escritura, actualización y eliminación en una base de datos para implementar la persistencia en la app de Forage. A continuación, se describe la app completa y su funcionalidad.

Cuando se inicia la app por primera vez, se muestra al usuario una pantalla vacía que contiene una vista de reciclador que mostrará elementos buscados, así como un botón flotante en la esquina inferior derecha a los efectos de agregar elementos nuevos.

3edd87e63c387d88.png

Cuando se agrega un elemento nuevo, el usuario puede especificar un nombre, la ubicación donde lo encontró y algunas notas adicionales. También hay una casilla de verificación para indicar si el alimento está en su temporada.

6c0c739569bb3b4f.png

Una vez que se agregue un elemento, este aparecerá en la vista de reciclador de la primera pantalla.

bcc75e60b70320e8.png

Cuando se presiona un elemento, se muestra una pantalla de detalles que muestra el nombre, la ubicación y las notas.

5096995a4921dcac.png

El botón flotante también cambia de un símbolo más a un ícono de edición. Cuando se presiona este botón, se muestra una pantalla donde se permite editar el nombre, la ubicación, las notas y la casilla de verificación de "producto en temporada". Cuando se presiona el botón Borrar, se quitará el elemento de la base de datos.

f8c708fed3dede1a.png

Si bien la parte de la IU de esta app ya está implementada, tu tarea es aplicar la persistencia usando tus conocimientos de Room, de modo que la app lea, escriba, actualice y borre elementos de la base de datos.

3. Cómo comenzar

Descarga el código del proyecto

Ten en cuenta que el nombre de la carpeta es android-basics-kotlin-forage-app. Selecciona esta carpeta cuando abras el proyecto en Android Studio.

A fin de obtener el código necesario para este codelab y abrirlo en Android Studio, haz lo siguiente:

Obtén el código

  1. Haz clic en la URL proporcionada. Se abrirá la página de GitHub del proyecto en un navegador.
  2. En esa página, haz clic en el botón Code, que abre un cuadro de diálogo.

5b0a76c50478a73f.png

  1. En el cuadro de diálogo, haz clic en el botón Download ZIP para guardar el proyecto en tu computadora. Espera a que se complete la descarga.
  2. Ubica el archivo en tu computadora (probablemente en la carpeta Descargas).
  3. Haz doble clic en el archivo ZIP para descomprimirlo. Se creará una carpeta nueva con los archivos del proyecto.

Abre el proyecto en Android Studio

  1. Inicia Android Studio.
  2. En la ventana Welcome to Android Studio, haz clic en Open an existing Android Studio project.

36cc44fcf0f89a1d.png

Nota: Si Android Studio ya está abierto, selecciona la opción de menú File > New > Import Project.

21f3eec988dcfbe9.png

  1. En el cuadro de diálogo Import Project, navega hasta donde se encuentra la carpeta de proyecto descomprimido (probablemente en Descargas).
  2. Haz doble clic en la carpeta del proyecto.
  3. Espera a que Android Studio abra el proyecto.
  4. Haz clic en el botón Run 11c34fc5e516fb1c.png para compilar y ejecutar la app. Asegúrate de que funcione como se espera.
  5. Explora los archivos del proyecto en la ventana de herramientas Project para ver cómo se configuró la app.

4. Configura el proyecto para usar Room

Define la entidad Forageable

El proyecto ya tiene una clase Forageable que define los datos de la app (model.Forageable.kt). Esta clase tiene varias propiedades: id, name, address, inSeason y notes.

data class Forageable(
   val id: Long = 0,
   val name: String,
   val address: String,
   val inSeason: Boolean,
   val notes: String?
)

Sin embargo, para usar esta clase a los efectos de almacenar datos persistentes, deberás convertirla en una entidad de Room.

  1. Anota la clase usando @Entity con el nombre de tabla "forageable_database".
  2. Haz que la propiedad id sea la clave primaria. Esta clave se debe generar automáticamente.
  3. Establece "in_season" como el nombre de la columna de la propiedad inSeason.

Implementa el DAO

Como podrás imaginar, ForageableDao (data.ForageableDao.kt) es donde defines los métodos para leer y escribir desde la base de datos a la que accederás desde el modelo de vista. Dado que el DAO es solo una interfaz que defines, no tendrás que escribir ningún código a fin de implementar estos métodos. En su lugar, debes usar anotaciones de Room y especificar la consulta en SQL cuando sea necesario.

Dentro de la interfaz ForageableDao, deberás agregar cinco métodos:

  1. Un método getForageables() que muestre un Flow<List<Forageable>> para todas las filas de la base de datos
  2. Un método getForageable(id: Long) que muestre un Flow<Forageable> que coincida con el id especificado
  3. Un método insert(forageable: Forageable) que inserte un elemento Forageable nuevo en la base de datos
  4. Un método update(forageable: Forageable) que tome un elemento Forageable existente como parámetro y actualice la fila según corresponda
  5. Un método delete(forageable: Forageable) que tome un elemento Forageable como parámetro y lo borre de la base de datos

Implementa ViewModel

ForageableViewModel (ui.viewmodel.ForageableViewModel.kt) se implementa de forma parcial, pero deberás agregar una funcionalidad que acceda a los métodos DAO para que pueda leer y escribir datos. Sigue estos pasos a fin de implementar ForageableViewModel.

  1. Se debe pasar una instancia de ForageableDao como parámetro en el constructor de la clase.
  2. Crea una variable de tipo LiveData<List<Forageable>> que obtenga la lista completa de entidades Forageable mediante el DAO y convierta el resultado en LiveData.
  3. Crea un método que tome un ID (de tipo Long) como parámetro y muestre un LiveData<Forageable> llamando desde el método getForageable() en el DAO y convirtiendo el resultado a LiveData.
  4. En el método addForageable(), inicia una corrutina usando el viewModelScope y utiliza el DAO para insertar la instancia Forageable en la base de datos.
  5. En el método updateForageable(), usa el DAO para actualizar la entidad Forageable.
  6. En el método deleteForageable(), usa el DAO para actualizar la entidad Forageable.
  7. Crea un ViewModelFactory que pueda crear una instancia de ForageableViewModel con un parámetro de constructor ForageableDao.

Implementa la clase Database

La clase ForageDatabase (data.ForageDatabase.kt) es lo que realmente expone tus entidades y DAO a Room. Implementa la clase ForageDatabase como se describe.

  1. Entidades: Forageable
  2. Versión: 1
  3. exportSchema: false
  4. Dentro de la clase ForageDatabase, incluye una función abstracta para mostrar un ForageableDao.
  5. Dentro de la clase ForageDatabase, define un objeto complementario con una variable privada llamada INSTANCE y una función getDatabase() que muestre el singleton ForageDatabase.
  1. En la clase BaseApplication, crea una propiedad database que muestre una instancia de ForageDatabase mediante la inicialización diferida.

5. Conserva y lee datos de los fragmentos

Una vez que hayas configurado las entidades, el DAO y el modelo de vista, y hayas definido la clase de base de datos para exponerlos a Room, lo único que queda por hacer es modificar los fragmentos a fin de acceder al modelo de vista. Deberás realizar cambios en tres archivos, uno para cada pantalla de la app.

Lista de elementos aptos para la búsqueda

La pantalla de la lista de elementos aptos para la búsqueda solo requiere dos cosas: una referencia al modelo de vista y acceso a la lista completa de esos elementos. Realiza las tareas que se indican a continuación en ui.ForageableListFragment.kt.

  1. La clase ya tiene una propiedad viewModel. Sin embargo, esto no usa la configuración de fábrica que definiste en el paso anterior. Primero deberás refactorizar esta declaración con el fin de usar la ForageableViewModelFactory.
private val viewModel: ForageableViewModel by activityViewModels {
   ForageableViewModelFactory(
       (activity?.application as BaseApplication).database.foragableDao()
   )
}
  1. Luego, en onViewCreated(), observa la propiedad allForageables desde el viewModel y llama a submitList() en el adaptador cuando corresponda para propagar la lista.

Pantalla de detalles de Forageable

Harás casi lo mismo para la lista detallada en ui/ForageableDetailFragment.kt.

  1. Convierte la propiedad viewModel a los efectos de inicializar la ForageableViewModelFactory de forma correcta.
  2. En onViewCreated(), llama a getForageable() en el modelo de vista y pasa id para obtener la entidad Forageable. Observa los datos en vivo y establece el resultado en la propiedad forageable. Luego, llama a bindForageable() para actualizar la IU.

Agrega y edita las pantallas de elementos aptos para la búsqueda

Por último, deberás hacer algo similar en ui.AddForageableFragment.kt. Ten en cuenta que esta pantalla también se encarga de actualizar y borrar entidades. Sin embargo, estos métodos del modelo de vista ya están en el lugar correcto. Solo deberás realizar dos cambios en este archivo:

  1. Una vez más, refactoriza la propiedad viewModel con el fin de usar ForageableViewModelFactory.
  2. En onViewCreated(), en el bloque de sentencia if antes de configurar la visibilidad del botón Borrar, llama a getForageable() en el modelo de vista, pasa el id y configura el resultado para la propiedad forageable.

Eso es todo lo que necesitas hacer en los fragmentos. Ahora puedes ejecutar tu app. Además, deberías poder ver todas las funciones de persistencia en acción.

6. Instrucciones para pruebas

Cómo realizar las pruebas

Para ejecutar las pruebas, puedes realizar una de las siguientes acciones:

Si se trata de un solo caso de prueba, abre una clase de caso de prueba, PersistenceInstrumentationTests.kt, y haz clic en la flecha verde que está a la izquierda de la declaración de la clase. Luego, puedes seleccionar la opción Run en el menú. Se ejecutarán todas las pruebas del caso de prueba.

3e640ec727599a6d.png

En general, te recomendamos que ejecutes una única prueba, por ejemplo, si hay una sola prueba fallida y las otras fueron exitosas. Puedes ejecutar una sola prueba como lo harías con todo el caso de prueba. Usa la flecha verde y selecciona la opción Run.

8647a76419540499.png

Si tienes varios casos de prueba, también podrás ejecutar todo el paquete de prueba. Al igual que cuando ejecutas la app, encontrarás esta opción en el menú Run.

7a925c5e196725bb.png

Ten en cuenta que Android Studio usará, de forma predeterminada, el último objetivo que ejecutaste (app, objetivos de prueba, etc.), por lo que, si el menú sigue indicando Run > Run 'app', podrás ejecutar el objetivo de prueba seleccionando Run > Run.

90d3ec5ca5928b2a.png

Luego, selecciona el objetivo de prueba en el menú emergente.

3b1a7d82a55b5f13.png