Pérdida de conexión — uno de los fenómenos más comunes y frustrantes en las aplicaciones móviles. El usuario pierde acceso a los datos, se interrumpe una operación, la aplicación se congela o se cierra. Según Google Android Developer Blog, el 70% de los usuarios eliminan una aplicación si se cierra o se congela dos veces. Analicemos las causas de la pérdida de conexión y las formas de construir comunicaciones tolerantes a fallos.
Puntos clave
Pérdida de conexión — término de usuario que describe una situación en la que la aplicación pierde la conexión con el servidor, deja de responder a las acciones o finaliza con un error. En términos técnicos, esto puede ser: error de red (tiempo de espera, fallo de DNS), ANR (congelación del hilo de UI), crash (excepción no controlada) o race condition (condición de carrera).
Desde la perspectiva del usuario, todos estos escenarios se ven igual: la aplicación deja de funcionar. La diferencia para los desarrolladores radica en el enfoque de diagnóstico y corrección. Los errores de red se resuelven con mecanismos de reintento, los ANR sacando operaciones del hilo de UI, los crashes con manejo de excepciones.
Según Crittercism (ahora Apteligent), en promedio una aplicación móvil pierde del 1 al 2% de usuarios con cada fallo. Para una aplicación con 1 millón de usuarios, esto significa de 10 a 20 mil instalaciones perdidas por un solo error. Esto es especialmente crítico para aplicaciones en los sectores financiero y médico.
Red inestable — los dispositivos móviles cambian constantemente entre Wi-Fi y red móvil, entrando en zonas sin cobertura (metro, ascensor, sótano). Cada cambio provoca una pérdida temporal de conexión que la aplicación debe manejar correctamente.
Tiempos de espera — si el servidor no responde dentro del tiempo de espera establecido (generalmente 10–30 segundos), el cliente lanza SocketTimeoutException. Los tiempos de espera largos sin retroalimentación son percibidos por el usuario como congelación. Se recomienda establecer un tiempo de espera de no más de 15 segundos.
val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build()
Condición de carrera (race condition) — ocurre cuando múltiples hilos leen y escriben los mismos datos simultáneamente sin sincronización. Por ejemplo, cargar datos de la caché en el hilo de UI mientras se actualiza la caché desde la red puede llevar a mostrar datos desactualizados o incorrectos.
Offline-first — un patrón arquitectónico donde el almacenamiento local (Room, CoreData) es la única fuente de verdad. La red se utiliza para la sincronización de datos en segundo plano. El usuario siempre ve datos actualizados de la caché local, incluso sin conexión de red.
Patrón Repository — un punto de entrada único para los datos que decide si obtener datos de la red o de la caché. El repositorio abstrae la fuente de datos del ViewModel y la UI. Ante un error de red, el repositorio cambia automáticamente a la fuente local.
class UserRepository(
private val api: UserApi,
private val dao: UserDao
) {
suspend fun getUsers(): Result<List<User>> {
return try {
val remote = api.fetchUsers()
dao.insertAll(remote)
Result.success(remote)
} catch (e: IOException) {
val cached = dao.getAll()
if (cached.isNotEmpty()) {
Result.success(cached) // return cache on network error
} else {
Result.failure(e)
}
}
}
}
Circuit Breaker — un patrón que protege al servidor de una avalancha de solicitudes cuando no está disponible. Después de N errores consecutivos, el interruptor se abre y todas las solicitudes devuelven inmediatamente un error sin intentar la conexión. Después de un tiempo de espera determinado, el interruptor pasa a un estado semiabierto para una solicitud de prueba.
Exponential backoff — un mecanismo de reintento estándar. Después del primer fallo, espere 1 segundo; después del segundo, 2 segundos; luego 4, 8, 16. Limite el número máximo de reintentos (generalmente 3–5) para no sobrecargar el servidor y la batería.
Retroalimentación al usuario — ante un error de red, muestre un mensaje claro: “Sin conexión”, “Servidor temporalmente no disponible”, “Verifique su internet”. Use Snackbar o Inline State View. Nunca muestre errores técnicos (HTTP 500, SocketException) al usuario.
ConnectivityManager — API de Android para monitoreo de red. Permita que la aplicación reaccione a los cambios: muestre un marcador de posición al perder la conexión, actualice automáticamente los datos al restaurarla. En iOS use NWPathMonitor del framework Network.
class NetworkMonitor(private val context: Context) {
private val manager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
fun isOnline(): Boolean {
val network = manager.activeNetwork ?: return false
val caps = manager.getNetworkCapabilities(network) ?: return false
return caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
}
Crashlytics (Firebase) — una herramienta estándar de reporte de fallos para aplicaciones móviles. Recopila stacktraces de todas las excepciones no controladas, versión del SO, modelo del dispositivo y hora del fallo. Permite agrupar errores y asignar responsables para las correcciones.
Sentry — una alternativa a Crashlytics con soporte de monitoreo de rendimiento. Permite rastrear transacciones específicas (por ejemplo, “autorización de usuario”) y ver en qué paso ocurrió un error. Performance tracing ayuda a distinguir los tiempos de espera de red de los errores en la lógica de la aplicación.
Timber — una biblioteca de registro para Android con adición automática de etiquetas por clase. En compilaciones de depuración, registre todas las solicitudes y respuestas de red. En compilaciones de lanzamiento, registre solo errores y advertencias a través de Crashlytics.setCustomLog.
| Herramienta | Tipo | Cuándo usarla |
|---|---|---|
| Crashlytics | Reporte de fallos | Siempre en release — recolección automática de fallos |
| Sentry | Fallos + Rendimiento | Cuando necesite perfilar escenarios de usuario específicos |
| Timber | Registro | Debug: registro completo; Release: solo errores |
| HTTP Toolkit | Depuración de red | Intercepción y análisis local de tráfico HTTP |
Según Firebase Summit 2023, las aplicaciones que implementaron Crashlytics + Performance Monitoring reducen el tiempo promedio de detección y corrección de errores críticos de 3 días a 4 horas. Se recomienda configurar alertas para cada fallo con una frecuencia superior al 0.1% de los usuarios activos.
Preguntas frecuentes
Si un crash no se detecta en Crashlytics, verifique fallos nativos (SIGSEGV, SIGABRT) — no son manejados por el controlador de excepciones de Java/Kotlin. En Android, esto podría ser una fuga de memoria nativa de JNI; en iOS, EXC_BAD_ACCESS. Use Breakpad (Android) o PLCrashReporter (iOS) para recopilar stacktraces de fallos nativos.
Use Network Link Conditioner (integrado en iOS; para Android, use Facebook Network Connection Class o Developer Options > Network > Select network type). Establezca un retraso de 500–3000 ms y una pérdida de paquetes del 5–30%. También puede usar Charles Proxy o mitmproxy para simular latencia y desconexiones de red.
ANR ocurre si el hilo de UI está bloqueado por más de 5 segundos. Las solicitudes de red deben ejecutarse en un hilo en segundo plano: corrutinas (viewModelScope.launch(Dispatchers.IO)), RxJava (subscribeOn(Schedulers.io)), o WorkManager para sincronización. Siempre establezca tiempos de espera en el cliente HTTP — la falta de tiempo de espera puede llevar a un bloqueo permanente.
Condición de carrera — una situación donde el resultado de una operación depende del orden de ejecución de los hilos. Por ejemplo, un usuario presiona rápidamente el botón “Enviar” dos veces, y la solicitud se envía dos veces. Solución: use Mutex, ejecutores de un solo hilo o una máquina de estados (desactive el botón después del primer clic). En Kotlin, use Mutex de corrutinas o la anotación @Synchronized.
Aplique Chaos Engineering para aplicaciones móviles: desconecte la red durante las operaciones, simule alta latencia, cambie entre Wi-Fi y red móvil, mate el proceso mediante el sistema. Herramientas: Facebook Network Connection Class, Charles Proxy, iOS Network Link Conditioner. En CI/CD, agregue pruebas de UI con diferentes condiciones de red a través de AndroidTest Orchestrator.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también