Aplicación Android nativa para la gestión integral de clínicas veterinarias
Características • Arquitectura • Instalación • Demo • Documentación
- Descripción General
- Características
- Stack Tecnológico
- Arquitectura
- Estructura del Proyecto
- Instalación
- Configuración
- Demo
- Módulos del Sistema
- Debug & Profiling
- Análisis de Memoria
- Testing
- APK Firmado
- Accesibilidad y Temas
- Flujo de Usuario
- Roadmap
- Autor
VetCare es una solución móvil completa diseñada para digitalizar y optimizar las operaciones diarias de clínicas veterinarias. La aplicación permite gestionar pacientes (mascotas), registrar consultas médicas, administrar la agenda de veterinarios y automatizar recordatorios de citas y vacunas para los propietarios de mascotas.
| Desafío | Solución VetCare |
|---|---|
| Gestión manual de expedientes | Sistema digital centralizado de mascotas |
| Agendamiento desorganizado | Calendario integrado con filtros avanzados |
| Falta de seguimiento médico | Historial completo de consultas y tratamientos |
| Olvido de citas/vacunas | Notificaciones automáticas programadas |
| Acceso limitado para dueños | Portal dedicado para propietarios |
| Módulo | Funcionalidades |
|---|---|
| 🔐 Autenticación | Login seguro, recuperación de contraseña, roles diferenciados |
| 🐾 Gestión de Mascotas | CRUD completo, historial médico, registro de vacunas |
| 📅 Agenda de Citas | Programación, filtros por estado, asignación de veterinarios |
| 👨⚕️ Staff Veterinario | Directorio, especialidades, agenda por profesional |
| 🔔 Notificaciones | Recordatorios automáticos de citas y vacunas |
| 📊 Dashboard Admin | Métricas en tiempo real, accesos rápidos |
| 💾 Persistencia Local | Room Database (SQLite), datos offline, sincronización automática |
| 📝 Registro de Actividad | Auditoría completa de acciones del sistema |
| 🔍 Debug & Profiling | Diagnóstico, métricas de rendimiento, manejo de errores |
| 🧠 Memory Profiling | LeakCanary, análisis de heap, detección de memory leaks |
| 🎨 Temas y Apariencia | Modo Claro, Oscuro y Automático (según sistema) |
| ♿ Accesibilidad | Alto contraste, reducción de animaciones, TalkBack |
| 🎯 UI/UX Premium | Material 3, animaciones fluidas, diseño adaptativo |
✅ Arquitectura MVVM con StateFlow reactivo
✅ Persistencia local con Room Database (SQLite)
✅ Operaciones CRUD completas sin conexión a internet
✅ TypeConverters para LocalDateTime y Enums
✅ Navegación declarativa con Compose Navigation
✅ Notificaciones con WorkManager
✅ Animaciones con AnimatedVisibility y animateContentSize
✅ Sistema de temas dinámico (Claro/Oscuro/Sistema)
✅ Soporte de accesibilidad (TalkBack, alto contraste)
✅ Componentes UI reutilizables
✅ Validación de formularios en tiempo real
✅ Manejo estructurado de excepciones con try-catch
✅ Sistema de logging avanzado con tags personalizados
✅ Excepciones personalizadas del dominio
✅ Métricas de rendimiento en tiempo real
✅ Herramientas de diagnóstico y profiling
✅ Detección de memory leaks con LeakCanary
✅ Análisis de memoria con Android Profiler
✅ Búsqueda con debounce optimizado (300ms)
✅ Localización completa en Español (ES-CL)
✅ Procesamiento asincrónico con Kotlin Coroutines
✅ Carga paralela de datos con async/await
✅ Dispatchers optimizados (IO, Default, Main)
✅ Pull-to-refresh sin bloqueo de UI
✅ Pruebas unitarias con JUnit y MockK (90+ tests)
✅ Pruebas funcionales instrumentadas con Compose UI Testing
✅ APK firmado (release) listo para distribución
✅ Ícono personalizado de Play Store (ic_launcher-playstore.png)
| Tecnología | Versión | Propósito |
|---|---|---|
| 2.0.21 | Lenguaje principal | |
| BOM 2024.09 | UI declarativa | |
| Latest | Sistema de diseño |
| Tecnología | Versión | Propósito |
|---|---|---|
| 2.7.0 | Base de datos SQLite | |
| SharedPreferences | - | Configuración de usuario |
| KSP | 2.0.21-1.0.28 | Procesador de anotaciones |
| Tecnología | Propósito |
|---|---|
| MVVM | Patrón de arquitectura |
| StateFlow | Gestión de estado reactivo |
| ViewModel | Persistencia de UI state |
| Repository Pattern | Abstracción de datos |
| Tecnología | Propósito |
|---|---|
| Navigation Compose | Navegación entre pantallas |
| WorkManager | Programación de notificaciones |
| Kotlin Coroutines | Procesamiento asincrónico optimizado |
| Tecnología | Versión | Propósito |
|---|---|---|
| 2.9.0 | Cliente HTTP para API REST | |
| 4.12.0 | Cliente HTTP subyacente + Interceptors | |
| 2.10.1 | Serialización JSON ↔ Objetos Kotlin |
| Componente | Propósito |
|---|---|
| viewModelScope | Coroutines lifecycle-aware |
| Dispatchers.IO | Operaciones de base de datos |
| Dispatchers.Default | Procesamiento CPU-intensive |
| async/await | Carga paralela de datos |
| Flow | Streams reactivos de Room |
El proyecto implementa Clean Architecture con el patrón MVVM (Model-View-ViewModel), garantizando separación de responsabilidades, testabilidad y mantenibilidad.
┌─────────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ Screens │◄───│ ViewModels │◄───│ UiState │ │
│ │ (Compose) │ │ (StateFlow) │ │ (Data Class) │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ DOMAIN LAYER │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Models │ │ Use Cases │ │
│ │ (Data Class) │ │ (Business) │ │
│ └─────────────────┘ └─────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ DATA LAYER │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ Repository │◄───│ DAOs │◄───│ Entities │ │
│ │ (Singleton) │ │ (Room/SQLite) │ │ (@Entity) │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Room Database │ │
│ │ (vetcare_database) │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
User Action → Screen → ViewModel → Repository → DAO → Room Database (SQLite)
↑ │
└──────────── StateFlow/Flow ◄────────────────┘
La aplicación implementa correctamente el patrón MVVM (Model-View-ViewModel) con separación clara de responsabilidades:
| Capa | Responsabilidad | Componentes |
|---|---|---|
| View (UI) | Renderizar UI, capturar eventos | *Screen.kt, *Components.kt (Jetpack Compose) |
| ViewModel | Estado de UI, lógica de presentación | *ViewModel.kt con StateFlow |
| Model (Data) | Datos y lógica de negocio | Repository, DAOs, Entities, Models |
┌─────────────────────────────────────────────────────────────────┐
│ UI LAYER │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ screens/ components/ navigation/ ││
│ │ - PetListScreen - Cards.kt - AppNavGraph.kt ││
│ │ - PetDetail... - Buttons.kt - NavRoutes.kt ││
│ │ - AdminHome... - InputFields.kt ││
│ │ ││
│ │ ✅ Solo UI declarativa, sin lógica de negocio ││
│ └─────────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────────┤
│ VIEWMODEL LAYER │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ *ViewModel.kt ││
│ │ - PetListViewModel - AdminHomeViewModel ││
│ │ - PetDetailViewModel - AuthViewModel ││
│ │ - AppointmentViewModel - ActivityLogViewModel ││
│ │ ││
│ │ ✅ StateFlow para estado reactivo ││
│ │ ✅ viewModelScope para coroutines lifecycle-aware ││
│ │ ✅ Sin referencias a Context/Activity ││
│ └─────────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────────┤
│ DATA LAYER │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ data/ ││
│ │ ├── model/ # Modelos de dominio (Pet, Owner...) ││
│ │ ├── local/ # Room Database, DAOs, Entities ││
│ │ ├── remote/ # Retrofit, DTOs, Mappers ││
│ │ ├── repository/ # VetCareRepository (singleton) ││
│ │ └── session/ # SessionManager ││
│ │ ││
│ │ ✅ Repository Pattern implementado ││
│ │ ✅ Separación Entity (Room) vs Model (Domain) ││
│ │ ✅ DTOs separados para API REST ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
| Principio MVVM | Estado | Evidencia |
|---|---|---|
| Single Source of Truth | ✅ Implementado | Room Database como fuente única |
| Unidirectional Data Flow | ✅ Implementado | UI → ViewModel → Repository → DB |
| Separation of Concerns | ✅ Implementado | 3 capas claramente separadas |
| Testability | ✅ Preparado | ViewModels sin dependencias de Android |
| Lifecycle Awareness | ✅ Implementado | viewModelScope, StateFlow |
Conclusión: La arquitectura MVVM está correctamente implementada y optimizada. No se requieren modificaciones estructurales.
La aplicación utiliza Room Database como capa de abstracción sobre SQLite, proporcionando:
- Operaciones offline: Todos los datos persisten localmente sin necesidad de conexión
- Type Safety: Verificación en tiempo de compilación de consultas SQL
- Reactive Streams: Integración nativa con Kotlin Coroutines y Flow
- Migrations: Soporte para actualizaciones de esquema de base de datos
La aplicación implementa procesamiento asincrónico avanzado para garantizar una experiencia de usuario fluida sin bloqueos ni congelamientos.
// Operaciones de Base de Datos → Dispatchers.IO
val pet = withContext(Dispatchers.IO) {
repository.getPetById(petId)
}
// Procesamiento de listas → Dispatchers.Default
val filteredList = withContext(Dispatchers.Default) {
appointments.filter { it.dateTime.isAfter(now) }.sortedBy { it.dateTime }
}
// Actualizaciones de UI → Dispatchers.Main (automático en viewModelScope)
_uiState.value = newState// Antes: Carga secuencial (~400ms con 4 operaciones de 100ms)
val owner = repository.getOwnerById(ownerId) // 100ms
val consultations = repository.getConsultations() // 100ms
val appointments = repository.getAppointments() // 100ms
val vaccines = repository.getVaccines() // 100ms
// Después: Carga paralela (~100ms total)
val ownerDeferred = async(Dispatchers.IO) { repository.getOwnerById(ownerId) }
val consultationsDeferred = async(Dispatchers.IO) { repository.getConsultations() }
val appointmentsDeferred = async(Dispatchers.IO) { repository.getAppointments() }
val vaccinesDeferred = async(Dispatchers.IO) { repository.getVaccines() }
// Todas las operaciones ejecutan simultáneamente
val owner = ownerDeferred.await()
val consultations = consultationsDeferred.await()| Pantalla | Optimización Implementada |
|---|---|
| PetDetailScreen | Carga paralela de owner, consultas, citas y vacunas |
| AdminDashboard | Cálculo de estadísticas en parallel con async/await |
| VeterinariansScreen | Carga paralela de estadísticas por veterinario |
| ActivityLog | Flow reactivo con procesamiento en Default dispatcher |
| Formularios | Guardado asincrónico sin bloqueo de UI |
| Aspecto | Kotlin Coroutines | RxJava |
|---|---|---|
| Sintaxis | Código secuencial natural | Cadenas de operadores |
| Curva de aprendizaje | Más suave | Más pronunciada |
| Integración Jetpack | Nativa (viewModelScope) | Requiere adaptadores |
| Manejo de errores | try/catch estándar | Operadores específicos |
| Tamaño de dependencia | Incluido en Kotlin | Biblioteca adicional |
| Cancelación | Structured concurrency | Disposables manuales |
Decisión: Se eligió Kotlin Coroutines por su integración nativa con Jetpack Compose, Room y ViewModel, además de proporcionar código más legible y mantenible.
app/
├── src/main/
│ ├── java/com/example/vetcare/
│ │ ├── VetCareApplication.kt # Application class (inicializa Room)
│ │ │
│ │ ├── data/
│ │ │ ├── local/
│ │ │ │ ├── VetCareDatabase.kt # Room Database principal
│ │ │ │ ├── Converters.kt # TypeConverters (DateTime, Enums)
│ │ │ │ │
│ │ │ │ ├── dao/ # Data Access Objects
│ │ │ │ │ ├── UserDao.kt
│ │ │ │ │ ├── OwnerDao.kt
│ │ │ │ │ ├── PetDao.kt
│ │ │ │ │ ├── VeterinarianDao.kt
│ │ │ │ │ ├── AppointmentDao.kt
│ │ │ │ │ ├── ConsultationDao.kt
│ │ │ │ │ ├── VaccineRecordDao.kt
│ │ │ │ │ └── ActivityEventDao.kt
│ │ │ │ │
│ │ │ │ ├── entity/ # Room Entities (@Entity)
│ │ │ │ │ ├── UserEntity.kt
│ │ │ │ │ ├── OwnerEntity.kt
│ │ │ │ │ ├── PetEntity.kt
│ │ │ │ │ ├── VeterinarianEntity.kt
│ │ │ │ │ ├── AppointmentEntity.kt
│ │ │ │ │ ├── ConsultationEntity.kt
│ │ │ │ │ ├── VaccineRecordEntity.kt
│ │ │ │ │ └── ActivityEventEntity.kt
│ │ │ │ │
│ │ │ │ └── mapper/
│ │ │ │ └── EntityMappers.kt # Conversión Entity ↔ Model
│ │ │ │
│ │ │ ├── remote/ # 🆕 Capa de Red (Retrofit)
│ │ │ │ ├── api/
│ │ │ │ │ └── VetCareApiService.kt # Interfaz Retrofit
│ │ │ │ ├── dto/
│ │ │ │ │ └── ApiDtos.kt # Data Transfer Objects
│ │ │ │ ├── mapper/
│ │ │ │ │ └── DtoMappers.kt # DTO ↔ Domain Mappers
│ │ │ │ ├── RetrofitClient.kt # Configuración Retrofit
│ │ │ │ ├── RemoteDataSource.kt # API Calls encapsuladas
│ │ │ │ └── NetworkResult.kt # Sealed class resultados
│ │ │ │
│ │ │ ├── logging/
│ │ │ │ └── ActivityLogger.kt # Sistema de auditoría
│ │ │ │
│ │ │ ├── model/ # Modelos de dominio
│ │ │ │ ├── User.kt
│ │ │ │ ├── Owner.kt
│ │ │ │ ├── Pet.kt
│ │ │ │ ├── Appointment.kt
│ │ │ │ ├── Veterinarian.kt
│ │ │ │ ├── Consultation.kt
│ │ │ │ ├── VaccineRecord.kt
│ │ │ │ └── ActivityEvent.kt
│ │ │ │
│ │ │ ├── repository/
│ │ │ │ └── VetCareRepository.kt # Repositorio unificado (Room)
│ │ │ │
│ │ │ └── session/
│ │ │ └── SessionManager.kt # Gestión de sesión
│ │ │
│ │ ├── debug/ # Herramientas de Debug & Profiling
│ │ │ ├── DebugLogger.kt # Sistema de logging avanzado
│ │ │ ├── VetCareExceptions.kt # Excepciones personalizadas
│ │ │ ├── DebugPetDetailViewModel.kt # ViewModel con métricas
│ │ │ └── DebugProfilingScreen.kt # Pantalla de diagnóstico
│ │ │
│ │ ├── notifications/
│ │ │ ├── ReminderScheduler.kt # Programador de recordatorios
│ │ │ └── ReminderWorkers.kt # Workers de citas y vacunas
│ │ │
│ │ ├── ui/
│ │ │ ├── accessibility/
│ │ │ │ └── AccessibilityUtils.kt # Utilidades de accesibilidad
│ │ │ │
│ │ │ ├── components/
│ │ │ │ ├── BottomNavigation.kt # Navegación inferior
│ │ │ │ ├── Cards.kt # Tarjetas personalizadas
│ │ │ │ ├── Buttons.kt # Botones con estilos
│ │ │ │ ├── InputFields.kt # Campos de entrada
│ │ │ │ ├── TopBars.kt # Barras superiores
│ │ │ │ └── Tabs.kt # Pestañas de filtro
│ │ │ │
│ │ │ ├── navigation/
│ │ │ │ ├── NavRoutes.kt # Definición de rutas
│ │ │ │ └── AppNavGraph.kt # Grafo de navegación
│ │ │ │
│ │ │ ├── screens/
│ │ │ │ ├── auth/ # Autenticación
│ │ │ │ ├── admin/ # Panel administrador
│ │ │ │ ├── owner/ # Panel propietario
│ │ │ │ ├── pets/ # Gestión de mascotas
│ │ │ │ ├── appointments/ # Gestión de citas
│ │ │ │ ├── veterinarians/ # Gestión de veterinarios
│ │ │ │ ├── consultations/ # Consultas médicas
│ │ │ │ ├── activity/ # Registro de actividad
│ │ │ │ ├── settings/ # Configuración
│ │ │ │ └── discover/ # Descubrir servicios
│ │ │ │
│ │ │ └── theme/
│ │ │ ├── Color.kt # Paletas de colores
│ │ │ ├── Theme.kt # Configuración del tema
│ │ │ ├── ThemeSettings.kt # Preferencias (SharedPreferences)
│ │ │ └── Typography.kt # Tipografía del sistema
│ │ │
│ │ └── MainActivity.kt
│ │
│ └── res/
│ ├── drawable/ # Assets de imágenes
│ └── values/ # Recursos (strings, colors)
│
├── build.gradle.kts # Configuración del módulo
└── gradle/
└── libs.versions.toml # Catálogo de versiones
- Android Studio Hedgehog | 2023.1.1 o superior
- JDK 17 o superior
- Android SDK API 26+ (Android 8.0)
- Gradle 8.0+
# 1. Clonar el repositorio
git clone https://github.com/yourusername/vetcare-android.git
# 2. Abrir en Android Studio
cd vetcare-android
# 3. Sincronizar dependencias
./gradlew build
# 4. Ejecutar en emulador o dispositivo
./gradlew installDebug| Variante | Uso |
|---|---|
debug |
Desarrollo y testing |
release |
Producción (requiere signing) |
| Rol | Contraseña | |
|---|---|---|
| Administrador | admin@vet.cl |
123456 |
| Propietario | owner@vet.cl |
123456 |
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />| Interfaz Administrador | Interfaz Cliente |
|---|---|
| Gestión completa: Dashboard, Mascotas, Citas, Staff y Auditoría | Experiencia del dueño: Mis Mascotas, Citas y Configuración |
Login → Dashboard → Gestión de Mascotas → Agenda de Citas → Staff → Registro de Actividad
Login → Mi Dashboard → Mis Mascotas → Mis Citas → Descubrir → Configuración
| Modo Claro | Modo Oscuro | Configuración |
|---|---|---|
| Interfaz clara optimizada para uso diurno | Interfaz oscura que reduce fatiga visual | Ajustes de tema y accesibilidad |
Las opciones de tema y accesibilidad están disponibles en Configuración → Apariencia/Accesibilidad
- Login con validación de credenciales
- Validación de email (patrón estándar)
- Validación de contraseña (mínimo 6 caracteres)
- Recuperación de contraseña con clave temporal
- Gestión de sesión persistente
- Logout con limpieza de estado
- Listado con filtros (especie, dueño, búsqueda)
- Ordenamiento múltiple
- CRUD completo (crear, leer, actualizar, eliminar)
- Perfil detallado con historial médico
- Registro de vacunas con fechas de aplicación
- Fotos de perfil con fallback visual
- Listado filtrable por estado (próximas, hoy, completadas, canceladas)
- Búsqueda por mascota o veterinario
- Creación con selección de fecha/hora
- Asignación de veterinario
- Cambio de estado
- Cancelación con confirmación
- Directorio completo del staff
- Información de especialidad y contacto
- Estadísticas por veterinario
- CRUD para administradores
- Agenda de citas por profesional
- Recordatorios automáticos de citas
- Alertas de vacunas próximas
- Implementación con WorkManager
- Cancelación automática al logout
La aplicación implementa un sistema de temas completo que se adapta a las preferencias del usuario:
| Modo | Descripción |
|---|---|
| ☀️ Claro | Fondo claro con texto oscuro, ideal para uso diurno |
| 🌙 Oscuro | Fondo oscuro que reduce fatiga visual en ambientes con poca luz |
| 🔄 Automático | Se adapta automáticamente según la configuración del sistema |
Implementación técnica:
- Persistencia de preferencias con SharedPreferences
- Colores dinámicos usando
CompositionLocal - Transición suave entre temas sin reiniciar la app
- Respeto por la configuración del sistema operativo
VetCare está diseñado siguiendo las pautas de accesibilidad de Android para garantizar una experiencia inclusiva:
| Característica | Descripción |
|---|---|
| Alto Contraste | Modo con colores más intensos para mejor legibilidad |
| Reducir Animaciones | Minimiza el movimiento para usuarios sensibles |
| TalkBack Compatible | contentDescription en todos los elementos interactivos |
| Áreas Táctiles | Mínimo 48dp en elementos clickeables |
| Jerarquía Visual | Tipografía diferenciada y espaciado consistente |
Ratios de contraste implementados:
| Modo | Background | Text | Ratio WCAG |
|---|---|---|---|
| Claro | #EEF1F7 | #12131A | 13.5:1 ✅ |
| Oscuro | #0F1117 | #E8E9ED | 14.2:1 ✅ |
| Alto Contraste | #FFFFFF | #000000 | 21:1 ✅ |
- Logging centralizado de acciones
- Filtros avanzados (fecha, pantalla, acción, usuario)
- Búsqueda en tiempo real
- Exportación de registros
- Visualización para auditoría
Módulo completo de herramientas de diagnóstico y monitoreo de rendimiento, accesible desde Configuración → Desarrollo → Debug & Profiling.
| Tag | Propósito |
|---|---|
VETCARE_DEBUG |
Logs generales de debugging |
VETCARE_PERF |
Métricas de rendimiento |
VETCARE_ERROR |
Errores y excepciones |
VETCARE_DB |
Operaciones de base de datos |
VETCARE_COROUTINE |
Flujos de coroutines |
VETCARE_VIEWMODEL |
Operaciones del ViewModel |
| Nivel | Uso |
|---|---|
| 🔍 DEBUG | Información detallada de desarrollo |
| ℹ️ INFO | Eventos importantes del flujo normal |
| Situaciones potencialmente problemáticas | |
| ❌ ERROR | Errores que no detienen la ejecución |
| 💀 FATAL | Errores críticos |
VetCareException (base)
├── DatabaseException // Errores de Room Database
├── EntityNotFoundException // Entidad no encontrada
├── TimeoutException // Operación excedió tiempo límite
├── ValidationException // Error de validación
├── AuthenticationException // Error de autenticación
├── SessionException // Sesión expirada
└── BusinessLogicException // Error de lógica de negocioLa pantalla de Debug & Profiling permite:
- Ejecutar flujos críticos con medición de tiempo
- Visualizar métricas de cada operación de BD
- Comparar rendimiento paralelo vs secuencial
- Detectar operaciones lentas (>500ms)
- Monitorear uso de memoria
- Simular errores para probar el manejo de excepciones
La aplicación ha sido sometida a un diagnóstico exhaustivo de gestión de memoria utilizando herramientas profesionales de profiling.
| Métrica | Valor | Estado |
|---|---|---|
| Total Memory | 156.1 MB | ✅ Normal |
| Java Heap | 16.7 MB | ✅ Óptimo |
| Native Memory | 19.8 MB | ✅ Normal |
| Objects in Memory | 118,228 | ✅ Controlado |
| Retained Size | ~2.7 MB | ✅ Saludable |
| Leaks Detected | 0 | ✅ Sin fugas |
| Duplicates | 0 | ✅ Sin duplicados |
Observaciones técnicas:
- El gráfico de memoria presenta comportamiento estable sin patrones de "escalera" (memoria que incrementa sin liberarse)
- No se detectó fragmentación de heap ni allocations excesivas durante la navegación
- El Garbage Collector (GC) ejecuta ciclos de recolección normales sin pausas prolongadas
- Las clases con mayor consumo (
EmojiCompat: 353 KB,Bitmap: 211 KB) están dentro de rangos normales para aplicaciones con UI
Se integró LeakCanary v2.14 como dependencia de debug para detección automática de fugas de memoria:
// app/build.gradle.kts
debugImplementation(libs.leakcanary.android)Flujos de prueba ejecutados:
- Navegación repetitiva: Dashboard → Mascotas → Detalle → Back (×10 iteraciones)
- Rotación de pantalla en múltiples Activities
- Apertura/cierre de diálogos y BottomSheets
- Ejecución de operaciones asíncronas con coroutines
- Destrucción de Activities y Fragments mediante navegación hacia atrás
Resultado del análisis: Los logs de LeakCanary (tag:LeakCanary) no reportaron instancias de APPLICATION LEAK ni ACTIVITY LEAK, confirmando:
| Componente | Estado | Verificación |
|---|---|---|
| ViewModels | ✅ Correcto | Se liberan al invocar onCleared() |
| Coroutines | ✅ Correcto | Cancelación automática con viewModelScope |
| Context References | ✅ Correcto | Sin referencias estáticas a Activity/Fragment |
| Listeners/Callbacks | ✅ Correcto | Desuscripción automática con lifecycle-aware pattern |
| Compose Functions | ✅ Correcto | Uso adecuado de remember y DisposableEffect |
La arquitectura MVVM implementada con Jetpack Compose, StateFlow y viewModelScope proporciona un manejo de ciclo de vida robusto que previene las fugas de memoria comunes en aplicaciones Android. Los componentes se liberan correctamente cuando salen del scope de composición o cuando las Activities/Fragments son destruidos.
Estado: ✅ Gestión de memoria óptima - Sin anomalías detectadas
La aplicación implementa una suite de pruebas exhaustiva que abarca tanto pruebas unitarias (JUnit + MockK) como pruebas funcionales instrumentadas (Compose UI Testing / Espresso), garantizando la calidad y confiabilidad del sistema.
Se desarrollaron 4 clases de prueba enfocadas en la validación de lógica de negocio, transformaciones de datos e integridad del modelo de dominio:
| Clase de Prueba | Tests | Propósito |
|---|---|---|
EntityMappersTest |
18 | Transformaciones bidireccionales Entity↔Model (User, Pet, Appointment, VaccineRecord, Owner) |
SessionManagerTest |
17 | Lógica de autenticación: login, logout, roles (Admin/Owner), estado de sesión |
ConvertersTest |
24 | TypeConverters de Room: LocalDateTime, LocalDate, Enums (UserRole, PetSpecies, AppointmentStatus) |
ModelValidationTest |
31 | Reglas de negocio, invariantes de datos, filtrado, ordenamiento y validaciones de formulario |
Ejecución:
./gradlew :app:testDebugUnitTestAspectos de lógica de negocio testeados:
- ✅ Integridad referencial en mappers (roundtrip Entity→Model→Entity)
- ✅ Serialización/deserialización de tipos complejos (ISO 8601)
- ✅ Gestión de estado de sesión (StateFlow reactivo)
- ✅ Validación de formularios (email, contraseña, edad de mascotas)
- ✅ Filtrado de mascotas por especie, dueño y búsqueda case-insensitive
- ✅ Ordenamiento de listas por nombre y edad
- ✅ Filtrado de citas por estado
- ✅ Manejo de valores nulos en campos opcionales
- ✅ Edge cases: strings inválidas, listas vacías, múltiples logouts
Se implementaron 2 clases de prueba instrumentada que simulan interacciones reales del usuario:
| Clase de Prueba | Tests | Pantalla Testeada |
|---|---|---|
LoginScreenTest |
8 | Pantalla de Login — Renderizado, ingreso de datos, navegación |
PetFormValidationTest |
5 | Formulario de Mascotas — Campos, chips de especie, navegación |
Ejecución (requiere emulador o dispositivo):
./gradlew :app:connectedDebugAndroidTestInteracciones de usuario verificadas:
- ✅ Renderizado correcto de componentes UI (logo, subtítulo, campos, botones)
- ✅ Ingreso de datos en campos de email y contraseña
- ✅ Callback de navegación "Olvidaste tu contraseña"
- ✅ Botón de login habilitado e interactuable
- ✅ Visualización de credenciales de prueba
- ✅ Flujo completo: Onboarding → Login → Dashboard → Mascotas → Formulario
- ✅ Visualización de campos del formulario de mascotas (nombre, especie, raza, edad)
- ✅ Selección de especie mediante chips (Perro, Gato, Ave, Conejo)
- ✅ Ingreso de texto en el campo nombre del formulario
- ✅ Navegación de vuelta desde el formulario a la lista de mascotas
- ✅ Estabilidad de la UI sin crashes
| Dependencia | Tipo | Propósito |
|---|---|---|
| JUnit 4.13.2 | testImplementation |
Framework de pruebas unitarias |
| MockK 1.13.8 | testImplementation |
Mocking de clases Kotlin |
| Coroutines Test 1.7.3 | testImplementation |
Testing de operaciones async |
| Arch Core Testing 2.2.0 | testImplementation |
Testing de LiveData/ViewModel |
| Compose UI Test JUnit4 | androidTestImplementation |
Framework de pruebas de UI Compose |
| Espresso Core 3.5.1 | androidTestImplementation |
Interacciones de UI instrumentadas |
| Navigation Testing 2.7.7 | androidTestImplementation |
Testing de navegación |
| Room Testing 2.7.0 | androidTestImplementation |
Testing de base de datos |
La aplicación cuenta con un APK firmado listo para distribución, generado con keystore dedicado.
| Parámetro | Valor |
|---|---|
| Nombre de la app | VetCare |
| Application ID | com.example.vetcare_android_kotlin_compose_mvvm |
| Version Code | 3 |
| Version Name | 1.3 |
| Min SDK | API 26 (Android 8.0) |
| Target SDK | API 35 (Android 15) |
| Compile SDK | API 36 |
| Ícono | Ícono personalizado (ic_launcher-playstore.png) |
| Signing | Keystore dedicado con configuración en signingConfigs |
| ProGuard | Configurado (proguard-rules.pro) |
Generación del APK:
./gradlew assembleReleaseEl APK firmado se encuentra en:
app/build/outputs/apk/release/app-release.apk
La aplicación implementa persistencia local completa utilizando Room Database, permitiendo operaciones sin conexión a internet.
┌─────────────────────────────────────────────────────────────────┐
│ vetcare_database │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ users │ │ owners │◄───│ pets │ │
│ │─────────────│ │─────────────│ │─────────────────────│ │
│ │ id (PK) │ │ id (PK) │ │ id (PK) │ │
│ │ email │ │ fullName │ │ ownerId (FK) │ │
│ │ passwordHash│ │ email │ │ name, species │ │
│ │ role │ │ phone │ │ breed, ageYears │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │ │
│ ┌─────────────────────┐ ┌──────────────────▼──────────────┐ │
│ │ veterinarians │ │ appointments │ │
│ │─────────────────────│ │─────────────────────────────────│ │
│ │ id (PK) │◄───│ id (PK) │ │
│ │ name, specialty │ │ petId (FK), vetId (FK) │ │
│ │ phone │ │ dateTime, reason, status │ │
│ └─────────────────────┘ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌─────────────────────────────────┐ │
│ │ consultations │ │ vaccine_records │ │
│ │─────────────────────│ │─────────────────────────────────│ │
│ │ id (PK) │ │ id (PK) │ │
│ │ petId (FK) │ │ petId (FK) │ │
│ │ vetId (FK) │ │ vaccineName │ │
│ │ diagnosis │ │ lastDate, nextDueDate │ │
│ │ treatment │ │ │ │
│ └─────────────────────┘ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
| Característica | Implementación |
|---|---|
| Base de datos | SQLite via Room 2.7.0 |
| Operaciones | CRUD completo (Create, Read, Update, Delete) |
| Relaciones | Foreign Keys con CASCADE delete |
| Tipos complejos | TypeConverters para LocalDateTime y Enums |
| Consultas | Flow para datos reactivos, suspend para operaciones |
| Inicialización | Datos de demostración precargados |
La aplicación integra Retrofit 2.9.0 como cliente HTTP para comunicación con APIs REST, preparando la arquitectura para futuras integraciones con backend.
| Criterio | Retrofit | HttpURLConnection | Ktor | Volley |
|---|---|---|---|---|
| Type Safety | ✅ Alto (interfaces) | ❌ Manual | ✅ Alto | |
| Boilerplate | ✅ Mínimo | ❌ Extenso | ✅ Mínimo | |
| Coroutines | ✅ Nativo | ❌ Manual | ✅ Nativo | ❌ Callbacks |
| Interceptors | ✅ OkHttp | ❌ Manual | ✅ Plugins | |
| Comunidad | ✅ Muy amplia | |||
| Documentación | ✅ Excelente | ✅ Buena | ||
| Mantenimiento | ✅ Square (activo) | ✅ Android | ✅ JetBrains |
Decisión: Se eligió Retrofit por:
- Estándar de la industria para Android (>90% de apps en producción)
- Integración nativa con Coroutines via funciones
suspend - OkHttp como base con interceptors para logging, auth y retry
- Conversión automática JSON ↔ Kotlin con Gson
- Mantenimiento activo por Square Inc.
┌─────────────────────────────────────────────────────────────────┐
│ NETWORK LAYER │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │ VetCareApi │ │ RetrofitClient │ │ OkHttp │ │
│ │ Service │◄───│ (Singleton) │◄───│ Client │ │
│ │ (Interface) │ │ + Gson │ │ +Interceptor│ │
│ └─────────────────┘ └─────────────────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ RemoteDataSource│ │ NetworkResult │ │
│ │ (API Calls) │───►│ (Success/Error) │ │
│ └─────────────────┘ └─────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ DTO Mappers │───►│ Domain Models │ │
│ │ (JSON ↔ Kotlin) │ │ (Pet, Owner..) │ │
│ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
data/remote/
├── api/
│ └── VetCareApiService.kt # Interfaz Retrofit con endpoints
├── dto/
│ └── ApiDtos.kt # Data Transfer Objects (JSON)
├── mapper/
│ └── DtoMappers.kt # Conversión DTO ↔ Domain Models
├── RetrofitClient.kt # Configuración singleton de Retrofit
├── RemoteDataSource.kt # Encapsulación de llamadas API
└── NetworkResult.kt # Sealed class para resultados
| Módulo | Endpoints | Métodos HTTP |
|---|---|---|
| Auth | /api/auth/login, /register, /reset-password |
POST |
| Pets | /api/pets, /pets/{id}, /pets/owner/{id} |
GET, POST, PUT, DELETE |
| Appointments | /api/appointments, /appointments/pet/{id} |
GET, POST, PUT, PATCH |
| Veterinarians | /api/veterinarians, /veterinarians/{id} |
GET |
| Consultations | /api/consultations/pet/{id} |
GET, POST |
| Vaccines | /api/vaccines/pet/{id} |
GET, POST |
| Owners | /api/owners/{id} |
GET, PUT |
// RetrofitClient.kt - Configuración centralizada
object RetrofitClient {
private val okHttpClient = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(loggingInterceptor) // Logging en debug
.addInterceptor { chain -> // Headers comunes
chain.proceed(chain.request().newBuilder()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.build())
}
.build()
}// NetworkResult.kt - Patrón sealed class
sealed class NetworkResult<out T> {
data class Success<out T>(val data: T) : NetworkResult<T>()
data class Error(val message: String, val code: Int?) : NetworkResult<Nothing>()
data object Loading : NetworkResult<Nothing>()
}
// Uso en ViewModel
when (result) {
is NetworkResult.Success -> _uiState.value = result.data
is NetworkResult.Error -> _error.value = result.message
is NetworkResult.Loading -> _isLoading.value = true
}| Aspecto | Decisión | Justificación |
|---|---|---|
| Sistema actual | Recursos locales (R.drawable.*) |
Imágenes embebidas en APK |
| Rendimiento | ✅ Óptimo | Sin latencia de red para cargar imágenes |
| Offline | ✅ Completo | Funciona sin conexión a internet |
| Tamaño APK | Trade-off aceptable para demo/prototipo | |
| Futuro | Glide cuando se integre backend | Cuando las imágenes vengan de servidor |
Conclusión: Glide se integrará en versión 2.0 cuando la app se conecte a un backend real con URLs de imágenes. Actualmente, el sistema de recursos locales es más eficiente para el caso de uso.
graph TD
A[Onboarding] --> B[Login]
B --> C{Rol?}
C -->|Admin| D[Dashboard Admin]
C -->|Owner| E[Dashboard Owner]
D --> F[Gestión Mascotas]
D --> G[Gestión Citas]
D --> H[Staff Veterinario]
D --> I[Activity Log]
D --> P[Configuración]
E --> J[Mis Mascotas]
E --> K[Mis Citas]
E --> L[Descubrir]
E --> Q[Configuración]
P --> R[Debug & Profiling]
Q --> R
F --> M[CRUD Mascotas]
G --> N[CRUD Citas]
H --> O[CRUD Veterinarios]
- Sistema de autenticación
- Gestión de mascotas (CRUD completo)
- Gestión de citas
- Gestión de veterinarios
- Notificaciones automáticas
- Registro de actividad
- UI/UX Material 3
- Sistema de temas (Claro/Oscuro/Automático)
- Accesibilidad (Alto contraste, TalkBack, reducir animaciones)
- Persistencia local con Room Database (SQLite)
- Operaciones offline sin conexión a internet
- Procesamiento asincrónico con Kotlin Coroutines
- Carga paralela de datos con async/await
- Dispatchers optimizados (IO para BD, Default para CPU)
- Pull-to-refresh sin bloqueo de UI
- Debounce en búsquedas (300ms)
- Fire-and-forget para logging de actividad
- Flow reactivo desde Room Database
- Sistema de logging avanzado con tags personalizados
- Excepciones personalizadas del dominio (VetCareExceptions)
- Herramientas de Debug & Profiling integradas
- Métricas de rendimiento en tiempo real
- Manejo estructurado de errores (try-catch)
- Simulación de errores para testing
- Actualización a Room 2.7.0
- Integración de LeakCanary v2.14 para detección de memory leaks
- Análisis exhaustivo con Android Profiler (heap dump, allocations, GC)
- Validación de gestión de memoria en flujos críticos
- Verificación de liberación correcta de ViewModels y Coroutines
- Confirmación de ausencia de referencias estáticas indebidas
- Documentación de métricas de memoria y resultados de análisis
- Integración de Retrofit 2.9.0 para API REST
- Configuración de OkHttp 4.12.0 con interceptors
- Serialización JSON con Gson 2.10.1
- Capa de red completa: DTOs, Mappers, DataSource
- NetworkResult sealed class para manejo de respuestas
- Endpoints preparados para 7 módulos (Auth, Pets, Appointments, etc.)
- Documentación de justificación técnica vs alternativas
- Generación de APK firmado (release) con keystore dedicado
- Configuración de
signingConfigsen build.gradle.kts - Actualización de versión:
versionCode = 3,versionName = "1.3" - Creación de ícono personalizado para Play Store (
ic_launcher-playstore.png) - Configuración de nombre de app, permisos y metadatos de distribución
- Redirección del build directory fuera de iCloud Drive para estabilidad de compilación
- ProGuard rules configuradas para release
- Integración con backend REST API
- Autenticación con Firebase Auth
- Sincronización cloud
- Chat en tiempo real
- Telemedicina veterinaria
- Pagos integrados
- Módulo de farmacia
- Gestión de inventario
- Reportes y analíticas avanzadas
- Multi-idioma (i18n)
- Backup automático en la nube
Este proyecto está bajo la Licencia MIT. Consulta el archivo LICENSE para más detalles.
Desarrollado con Kotlin, Jetpack Compose & Room Database
⭐ Si este proyecto te resultó útil, considera darle una estrella
¡Las contribuciones son bienvenidas! Este proyecto está abierto a la comunidad y agradecemos toda ayuda para mejorarlo.
- Lee la guía: Revisa CONTRIBUTING.md para conocer las normas de contribución
- Encuentra un issue: Busca issues etiquetados como
good first issue - Fork & Branch: Crea un fork y una rama para tu contribución
- Desarrolla: Implementa tu mejora siguiendo las convenciones de código
- Testing: Asegúrate de que todos los tests pasen
- Pull Request: Envía tu PR con una descripción clara
- 🎨 UI/UX: Mejoras visuales, animaciones, Material Design 3
- 🧪 Testing: Tests unitarios, tests de UI, cobertura
- ♿ Accesibilidad: Soporte TalkBack, contraste, navegación
- ⚡ Performance: Optimizaciones, lazy loading, caching
- 🌍 i18n: Traducciones y localización
- 📱 Features: Nuevas funcionalidades para clínicas veterinarias
- 📚 Documentación: Mejoras en docs, tutoriales, ejemplos
Perfecto para comenzar:
- #1 🌙 Agregar soporte para tema oscuro
- #2 ♿ Mejorar soporte de TalkBack
- #3 ⚡ Optimizar rendimiento de listas
- #4 🧪 Agregar tests unitarios
- #5 🌍 Mejorar traducciones al español
Ver todos los Good First Issues →
Este proyecto sigue el Código de Conducta de Contributor Covenant. Al participar, aceptas mantener un ambiente respetuoso y acogedor para todos.
Gracias a todas las personas que han contribuido a VetCare:








