Odpadává — co to je, typické příčiny a metody řešení

Autor: IT Sectr Publikováno: 2026-07-29 Doba čtení: 10 min

Ztráta spojení — jeden z nejčastějších a nejotravnějších jevů v mobilních aplikacích. Uživatel ztrácí přístup k datům, operace je přerušena, aplikace zamrzá nebo padá. Podle Google Android Developer Blog 70% uživatelů odstraňuje aplikaci, pokud dvakrát spadne nebo zamrzne. Rozebereme příčiny ztráty spojení a způsoby budování odolných komunikací.

Hlavní body

  • ANR (Application Not Responding) — blokování vlákna UI déle než 5 sekund vede k vynucenému ukončení
  • Offline-first — architektura, kde lokální úložiště je zdrojem pravdy a síť mechanismem synchronizace
  • Retry with backoff — automatické opakování požadavku s rostoucím zpožděním při síťových chybách
  • ConnectivityManager — Android API pro sledování stavu sítě a přizpůsobení chování aplikace
  • Graceful degradation — aplikace by měla fungovat (alespoň částečně) při absenci sítě

Co znamená „odpadává” v mobilních aplikacích?

Odpadává — uživatelský termín popisující situaci, kdy aplikace ztrácí spojení se serverem, přestává reagovat na akce nebo končí chybou. V technickém smyslu to může být: síťová chyba (timeout, DNS failure), ANR (blokování vlákna UI), crash (neošetřená výjimka) nebo race condition (soutěžní stav).

Pro uživatele všechny tyto scénáře vypadají stejně: aplikace přestane fungovat. Rozdíl pro vývojáře spočívá v přístupu k diagnostice a opravě. Síťové chyby se řeší mechanismy retry, ANR — přenesením operací mimo vlákno UI, crash — ošetřením výjimek.

Podle Crittercism (nyní Apteligent) průměrná mobilní aplikace ztrácí 1-2% uživatelů při každém pádu. Pro aplikaci s 1 milionem uživatelů to znamená 10-20 tisíc ztracených instalací na jednu chybu. Zvláště kritické je to pro aplikace ve finančním a lékařském sektoru.

Hlavní příčiny ztráty spojení

Nestabilní síť — mobilní zařízení neustále přepínají mezi Wi-Fi a mobilní sítí, vstupují do zón bez pokrytí (metro, výtah, sklep). Každé přepnutí způsobuje dočasnou ztrátu spojení, kterou musí aplikace správně zpracovat.

Časové limity — pokud server neodpoví ve stanoveném čase (obvykle 10-30 sekund), klient vyvolá SocketTimeoutException. Dlouhé časové limity bez zpětné vazby jsou uživatelem vnímány jako zamrznutí. Doporučuje se nastavit časový limit maximálně 15 sekund.

kotlin
val client = OkHttpClient.Builder()
    .connectTimeout(10, TimeUnit.SECONDS)
    .readTimeout(15, TimeUnit.SECONDS)
    .writeTimeout(15, TimeUnit.SECONDS)
    .retryOnConnectionFailure(true)
    .build()

Soutěžní stav (race condition) — vzniká, když několik vláken současně čte a zapisuje stejná data bez synchronizace. Například načítání dat z mezipaměti ve vlákně UI paralelně s aktualizací mezipaměti ze sítě může vést k zobrazení zastaralých nebo nesprávných dat.

  • Neošetřené výjimky v callback nebo coroutine vedou k pádu aplikace
  • Tlak na paměť — systém zabíjí aplikaci při nedostatku paměti pro aplikaci v popředí
  • Lifecycle race — async operace se dokončí po zničení Activity/Fragment
  • Blokování UI — provádění sítě nebo databáze v hlavním vlákně způsobí ANR po 5 sekundách

Architektura pro odolné aplikace

Offline-first — architektonický vzor, kde lokální úložiště (Room, CoreData) je jediným zdrojem pravdy. Síť se používá pro synchronizaci dat na pozadí. Uživatel vždy vidí aktuální data z lokální mezipaměti, i při absenci sítě.

Repository pattern — jednotný vstupní bod pro data, který rozhoduje, zda data vzít ze sítě nebo z mezipaměti. Repozitář abstrahuje zdroj dat od ViewModel a UI. Při síťové chybě repozitář automaticky přepne na lokální zdroj.

kotlin
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) // vrátit mezipaměť při síťové chybě
            } else {
                Result.failure(e)
            }
        }
    }
}

Circuit Breaker — vzor ochrany serveru před lavinou požadavků při nedostupnosti. Po N po sobě jdoucích chybách se vypínač otevře a všechny požadavky okamžitě vracejí chybu bez pokusu o připojení. Po stanoveném časovém limitu přejde vypínač do polootevřeného stavu pro zkušební požadavek.

Jak zpracovávat síťové chyby?

Exponential backoff — standardní mechanismus retry. Po prvním neúspěchu počkejte 1 sekundu, po druhém — 2 sekundy, poté 4, 8, 16. Omezte maximální počet pokusů (obvykle 3-5), abyste nepřetěžovali server a baterii.

Zpětná vazba uživateli — při síťové chybě zobrazte srozumitelnou zprávu: „Žádné připojení”, „Server je dočasně nedostupný”, „Zkontrolujte internet”. Použijte Snackbar nebo Inline State View. Nikdy neukazujte uživateli technické chyby (HTTP 500, SocketException).

ConnectivityManager — Android API pro monitorování sítě. Umožněte aplikaci reagovat na změny: při ztrátě sítě zobrazte placeholder, při obnovení — automaticky aktualizujte data. V iOS použijte NWPathMonitor z frameworku Network.

kotlin
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)
    }
}

Nástroje monitorování a logování

Crashlytics (Firebase) — standardní nástroj pro hlášení pádů pro mobilní aplikace. Sbírá stacktrace všech neošetřených výjimek, verzi OS, model zařízení a čas pádu. Umožňuje seskupovat chyby a přiřazovat odpovědné osoby za opravy.

Sentry — alternativa k Crashlytics s podporou monitorování výkonu. Umožňuje trasovat konkrétní transakce (např. „autorizace uživatele”) a vidět, ve kterém kroku došlo k chybě. Performance tracing pomáhá odlišit síťové časové limity od chyb v logice aplikace.

Timber — knihovna pro logování pro Android s automatickým přidáváním značek podle třídy. V debug sestavení logujte všechny síťové požadavky a odpovědi. V release sestavení — pouze chyby a varování přes Crashlytics.setCustomLog.

NástrojTypKdy použít
CrashlyticsCrash reportingVždy v release — automatický sběr pádů
SentryCrash + PerformanceKdyž potřebujete profilovat konkrétní uživatelské scénáře
TimberLoggingDebug: plné logování; Release: pouze chyby
HTTP ToolkitNetwork debugLokální zachycení a analýza HTTP provozu

Podle Firebase Summit 2023 aplikace, které zavedly Crashlytics + Performance Monitoring, zkracují průměrnou dobu detekce a opravy kritických chyb ze 3 dnů na 4 hodiny. Doporučuje se nastavit výstrahy na každý pád s frekvencí vyšší než 0.1% aktivních uživatelů.

Často kladené otázky

Co dělat, když aplikace spadne bez chybové zprávy?

Pokud crash není zachycen v Crashlytics, zkontrolujte native crash (SIGSEGV, SIGABRT) — ty nezpracovává Java/Kotlin exception handler. V Androidu to může být únik native paměti z JNI, v iOS — EXC_BAD_ACCESS. Použijte Breakpad (Android) nebo PLCrashReporter (iOS) pro sběr stacktrace native crash.

Jak reprodukovat chybu, která se projevuje jen při slabé síti?

Použijte Network Link Conditioner (vestavěný v iOS, pro Android existuje Facebook Network Connection Class nebo nastavení Developer Options > Network > Select network type). Nastavte zpoždění 500-3000 ms a ztrátu paketů 5-30%. Také můžete použít Charles Proxy nebo mitmproxy pro emulaci síťových zpoždění a přerušení.

Jak zabránit ANR při síťových požadavcích?

ANR vzniká, když je vlákno UI blokováno déle než 5 sekund. Síťové požadavky by měly být prováděny na vlákně na pozadí: coroutines (viewModelScope.launch(Dispatchers.IO)), RxJava (subscribeOn(Schedulers.io)) nebo WorkManager pro synchronizaci. Vždy nastavujte časové limity na HTTP klientovi — absence časového limitu může vést k věčnému blokování.

Co je race condition a jak se mu vyhnout?

Race condition — situace, kdy výsledek operace závisí na pořadí provádění vláken. Například uživatel rychle dvakrát stiskne tlačítko „Odeslat” a požadavek je odeslán dvakrát. Řešení: použijte Mutex, single-threaded executors nebo state machine (deaktivujte tlačítko po prvním stisknutí). V Kotlin použijte Mutex z coroutines nebo anotaci @Synchronized.

Jak testovat odolnost aplikace?

Aplikujte Chaos Engineering pro mobilní aplikace: vypněte síť během operací, simulujte vysoké zpoždění, přepínejte mezi Wi-Fi a mobilní sítí, zabijte proces systémem. Nástroje: Facebook Network Connection Class, Charles Proxy, iOS Network Link Conditioner. V CI/CD přidejte UI testy s různými síťovými podmínkami přes AndroidTest Orchestrator.

Shrnutí

  • Odpadává — souhrnný termín pro síťové chyby, ANR, crash a race conditions; uživatelský zážitek je stejný, příčiny různé
  • Síťové chyby — nejčastější příčina; řešení zahrnuje časové limity (10-15 sekund), exponential backoff a offline-first architekturu
  • ANR vzniká při blokování vlákna UI déle než 5 sekund; síťové a diskové operace vždy provádějte na vlákně na pozadí
  • Offline-first s Repository pattern: lokální úložiště — zdroj pravdy, síť — mechanismus synchronizace
  • Crashlytics + Performance Monitoring — minimální sada pro monitorování produkce s výstrahami na časté pády
  • Soutěžní stav vyžaduje synchronizaci vláken: Mutex, State Machine nebo jednovláknový executor
  • Testujte s emulací slabé sítě a Chaos Engineering — jen tak můžete odhalit problémy skryté v ideálních podmínkách vývoje

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také