Prácticas_aplicadas_para_evitar_ANRs - 5x5x5-cube/vinilos-app GitHub Wiki
Durante el desarrollo del Sprint 2 del proyecto Vinilos App, el equipo aplicó una serie de buenas prácticas orientadas a prevenir errores tipo ANR (Application Not Responding). Estas prácticas se enfocaron principalmente en garantizar que las operaciones de red y de acceso a base de datos se ejecuten en hilos de fondo, evitando bloquear el hilo principal de la aplicación.
A continuación se detallan las medidas implementadas:
Todos los métodos que realizan llamadas a la red (como getAlbums
, getAlbum
, getCollectors
, getPerformers
, entre otros) fueron definidos como funciones suspend
y envueltos con suspendCoroutine
. Esto permite que estas operaciones de red se ejecuten de forma asincrónica sin bloquear el hilo principal:
suspend fun getAlbums() = suspendCoroutine<List<Album>> { cont ->
// Request asíncrona con Volley
}
En los archivos AlbumRepository.kt
, CollectorRepository.kt
y PerformerRepository.kt
, se delegan las llamadas de red directamente al NetworkServiceAdapter
y estas se invocan también desde funciones suspend
. Esto permite que el ViewModel pueda llamarlas desde un Dispatchers.IO
, lo cual está diseñado para operaciones intensivas de I/O:
suspend fun getAlbum(albumId: Int): AlbumDetails {
return NetworkServiceAdapter.getInstance(application).getAlbum(albumId)
}
En los ViewModels (AlbumDetailViewModel.kt
, AlbumViewModel.kt
, CollectorViewModel.kt
, PerformerViewModel.kt
, PerformerDetailViewModel.kt
), se emplea viewModelScope.launch(Dispatchers.Default)
en conjunto con withContext(Dispatchers.IO)
para ejecutar las operaciones de red en hilos apropiados:
viewModelScope.launch(Dispatchers.Default) {
withContext(Dispatchers.IO) {
val data = albumsRepository.getAlbum(id)
_albumOriginal.postValue(data)
}
}
Esto garantiza que las tareas de red o de base de datos no se realicen en el hilo principal, previniendo cuelgues o bloqueos que pueden causar un ANR.
Cada operación crítica de carga de datos en los ViewModels está envuelta en un bloque try-catch
para prevenir que una excepción no controlada interrumpa el flujo de la app y cause bloqueos prolongados:
try {
viewModelScope.launch(Dispatchers.Default) {
}
} catch (e: Exception) {
_eventNetworkError.value = true
}