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.
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.
Una vez que se agregue un elemento, este aparecerá en la vista de reciclador de la primera pantalla.
Cuando se presiona un elemento, se muestra una pantalla de detalles que muestra el nombre, la ubicación y las notas.
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.
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.
Para obtener el código necesario para este codelab y abrirlo en Android Studio, haz lo siguiente:
Obtén el código
- Haz clic en la URL proporcionada. Se abrirá la página de GitHub del proyecto en un navegador.
- En esa página, haz clic en el botón Code, que abre un cuadro de diálogo.
- 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.
- Ubica el archivo en tu computadora (probablemente en la carpeta Descargas).
- 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
- Inicia Android Studio.
- En la ventana Welcome to Android Studio, haz clic en Open an existing Android Studio project.
Nota: Si Android Studio ya está abierto, selecciona la opción de menú File > New > Import Project.
- En el cuadro de diálogo Import Project, navega hasta donde se encuentra la carpeta de proyecto descomprimido (probablemente en Descargas).
- Haz doble clic en la carpeta del proyecto.
- Espera a que Android Studio abra el proyecto.
- Haz clic en el botón Run para compilar y ejecutar la app. Asegúrate de que funcione como se espera.
- 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.
- Anota la clase usando
@Entity
con el nombre de tabla"forageable_database"
. - Haz que la propiedad
id
sea la clave primaria. Esta clave se debe generar automáticamente. - Establece
"in_season"
como el nombre de la columna de la propiedadinSeason
.
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 para 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:
- Un método
getForageables()
que muestre unFlow<List<Forageable>>
para todas las filas de la base de datos - Un método
getForageable(id: Long)
que muestre unFlow<Forageable>
que coincida con elid
especificado - Un método
insert(forageable: Forageable)
que inserte un elementoForageable
nuevo en la base de datos - Un método
update(forageable: Forageable)
que tome un elementoForageable
existente como parámetro y actualice la fila según corresponda - Un método
delete(forageable: Forageable)
que tome un elementoForageable
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 para implementar ForageableViewModel
.
- Se debe pasar una instancia de
ForageableDao
como parámetro en el constructor de la clase. - Crea una variable de tipo
LiveData<List<Forageable>>
que obtenga la lista completa de entidadesForageable
mediante el DAO y convierta el resultado enLiveData
. - Crea un método que tome un ID (de tipo
Long
) como parámetro y muestre unLiveData<Forageable>
llamando desde el métodogetForageable()
en el DAO y convirtiendo el resultado aLiveData
. - En el método
addForageable()
, inicia una corrutina usando elviewModelScope
y utiliza el DAO para insertar la instanciaForageable
en la base de datos. - En el método
updateForageable()
, usa el DAO para actualizar la entidadForageable
. - En el método
deleteForageable()
, usa el DAO para actualizar la entidadForageable
. - Crea un
ViewModelFactory
que pueda crear una instancia deForageableViewModel
con un parámetro de constructorForageableDao
.
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.
- Entidades:
Forageable
- Versión:
1
- exportSchema:
false
- Dentro de la clase
ForageDatabase
, incluye una función abstracta para mostrar unForageableDao
. - Dentro de la clase
ForageDatabase
, define un objeto complementario con una variable privada llamadaINSTANCE
y una funcióngetDatabase()
que muestre el singletonForageDatabase
.
- En la clase
BaseApplication
, crea una propiedaddatabase
que muestre una instancia deForageDatabase
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 para 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.
- 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 para usarForageableViewModelFactory
.
private val viewModel: ForageableViewModel by activityViewModels {
ForageableViewModelFactory(
(activity?.application as BaseApplication).database.foragableDao()
)
}
- Luego, en
onViewCreated()
, observa la propiedadallForageables
desdeviewModel
y llama asubmitList()
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.
- Convierte la propiedad
viewModel
a los efectos de inicializarForageableViewModelFactory
de forma correcta. - En
onViewCreated()
, llama agetForageable()
en el modelo de vista y pasaid
para obtener la entidadForageable
. Observa los datos en vivo y establece el resultado en la propiedadforageable
. Luego, llama abindForageable()
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:
- Una vez más, refactoriza la propiedad
viewModel
para usarForageableViewModelFactory
. - En
onViewCreated()
, en el bloque de la sentencia "if" antes de configurar la visibilidad del botón Borrar, llama agetForageable()
en el modelo de vista, pasa elid
y configura el resultado para la propiedadforageable
.
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.
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.
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.
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.
Luego, selecciona el objetivo de prueba en el menú emergente.