Listar, visualizar y gestionar preórdenes en Android Studio
Clase 17 de 19 • Curso de Android: Modo Offline con Room y Realm
Contenido del curso
- 4

Implementación de la Capa de Datos con Clean Architecture
10:17 - 5

Integración de Remote Data Storage con Vis Order API en Android
03:01 - 6

Integración de Room como Base de Datos en Android
18:08 - 7

Integración de Real en Android: Dependencias y Objetos de Datos
22:50 quiz de Arquitectura y Almacenamiento de Datos
- 8

Creación de Entidades y Repositorios en la Capa de Dominio en Android Studio
07:05 - 9

Implementación de LocalStorage con Room y Realm en Android Studio
13:33 - 10

Implementación de Repositorios en Android: Remote y Local Storage
11:49 - 11

Implementación de Repositorio para Preórdenes en Android Studio
09:55 quiz de Repositorios y Gestión de Datos
- 12

Creación de UI en Android: Composables y StateFlow con Hilt
26:26 - 13

Corrección de Errores en Android Studio y Visualización de Órdenes
09:59 - 14

Implementación de Barra de Navegación Inferior en Android Compose
13:05 - 15

Creación de un Detail Screen en Jetpack Compose para Android
25:50 - 16

Formulario de Preorden en Android Studio con Compose
20:02 - 17

Listar, visualizar y gestionar preórdenes en Android Studio
23:59 quiz de Capa de Presentación y Navegación
La gestión de preórdenes en aplicaciones Android es fundamental para ofrecer una experiencia de usuario fluida, especialmente cuando se trabaja con funcionalidades offline. Dominar la visualización, eliminación y sincronización de datos locales con servicios remotos te permitirá crear aplicaciones robustas que funcionen incluso sin conexión a internet.
¿Cómo implementar la visualización de preórdenes en Android?
Para visualizar las preórdenes creadas previamente, necesitamos reutilizar el ViewModel existente y crear una nueva pantalla. Aunque esto podría considerarse una ligera desviación del principio de responsabilidad única de SOLID, es una solución práctica para nuestro caso.
Creación del estado de la UI
El primer paso es definir una clase de estado para nuestra interfaz:
data class PreOrderState(
val isLoading: Boolean = false,
val data: List<PreOrder> = emptyList(),
val isError: Boolean = false
)
A continuación, creamos un StateFlow para manejar el estado de la vista:
val preOrderState: StateFlow<PreOrderState> = preOrderRepository.getPreOrders()
.map { result ->
result.fold(
onSuccess = { data ->
PreOrderState(isLoading = false, data = data, isError = false)
},
onFailure = {
PreOrderState(isLoading = false, data = emptyList(), isError = true)
}
)
}
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(5000),
PreOrderState(isLoading = true)
)
Implementación de funciones para eliminar y sincronizar
Además de visualizar las preórdenes, necesitamos funcionalidades para eliminarlas localmente o sincronizarlas con el servidor:
fun delete(id: Long) {
preOrderRepository.delete(id)
}
fun onSync(id: Long) {
preOrderRepository.onRetrySync(id)
}
¿Cómo diseñar la interfaz de usuario para mostrar las preórdenes?
Una vez que tenemos la lógica de negocio implementada, procedemos a crear la interfaz de usuario utilizando Jetpack Compose.
Creación de la pantalla principal
@Composable
fun PreOrdersScreen(
modifier: Modifier = Modifier,
viewModel: PreOrderViewModel = hiltViewModel()
) {
val state by viewModel.preOrderState.collectAsState()
when {
state.isLoading -> {
// Mostrar indicador de carga
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}
state.isError -> {
// Mostrar mensaje de error
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Error al cargar las preórdenes")
}
}
else -> {
LazyColumn(
modifier = modifier
.fillMaxSize()
.padding(start = 8.dp, top = 16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
items(state.data) { item ->
PreOrderItem(
item = item,
onSync = { id -> viewModel.onSync(id) },
onDelete = { id -> viewModel.delete(id) }
)
}
}
}
}
}
Diseño del elemento individual de preorden
Para cada preorden, creamos un componente reutilizable que muestra la información relevante y proporciona opciones para sincronizar o eliminar:
@Composable
fun PreOrderItem(
item: PreOrder,
onSync: (Long) -> Unit,
onDelete: (Long) -> Unit
) {
var expanded by remember { mutableStateOf(false) }
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.background(
MaterialTheme.colorScheme.surface,
shape = RoundedCornerShape(8.dp)
),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = item.customerName,
style = MaterialTheme.typography.titleLarge
)
Text(
text = item.product,
style = MaterialTheme.typography.bodyLarge
)
}
Icon(
modifier = Modifier.size(24.dp),
imageVector = if (item.isSent) Icons.Default.CheckCircle else Icons.Default.Warning,
contentDescription = if (item.isSent) "Enviado" else "Pendiente",
tint = if (item.isSent) MaterialTheme.colorScheme.primary else if (item.isError) Color.Red else Color.Green
)
if (item.isSent) {
Spacer(modifier = Modifier.width(48.dp))
} else {
Box {
IconButton(
onClick = { expanded = true }
) {
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = "Más opciones"
)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
onClick = {
onSync(item.id)
expanded = false
},
text = { Text("Sincronizar") }
)
DropdownMenuItem(
onClick = {
onDelete(item.id)
expanded = false
},
text = { Text("Eliminar") }
)
}
}
}
}
}
Previsualización del componente
Para facilitar el desarrollo, es útil crear una previsualización del componente:
@Preview(showBackground = true)
@Composable
fun PreviewPreOrderItem() {
PreOrderItem(
item = PreOrder(
id = 1L,
customerName = "Cliente de prueba",
product = "Producto de prueba",
isSent = false
),
onSync = {},
onDelete = {}
)
}
¿Cómo integrar la pantalla en la navegación principal?
Finalmente, integramos nuestra nueva pantalla en la navegación principal de la aplicación:
// En MainScreen.kt
PreOrdersScreen(
modifier = Modifier.padding(paddingValues)
)
Al ejecutar la aplicación, podemos ver las preórdenes creadas anteriormente. Las que tienen un icono de verificación ya han sido sincronizadas con el servidor, mientras que las que muestran un icono de advertencia están almacenadas localmente y pueden ser sincronizadas o eliminadas.
La funcionalidad offline es crucial en aplicaciones móviles modernas, ya que permite a los usuarios seguir trabajando incluso cuando no tienen conexión a internet. Al implementar correctamente la sincronización, podemos ofrecer una experiencia fluida donde los datos se guardan localmente y se envían al servidor cuando hay conexión disponible.
¿Has implementado alguna vez funcionalidades offline en tus aplicaciones? Comparte tu experiencia y los desafíos que encontraste en los comentarios.