Kapcsolat elvesztése — az egyik leggyakoribb és legidegesítőbb jelenség mobilalkalmazásokban. A felhasználó elveszíti a hozzáférést az adatokhoz, a művelet megszakad, az alkalmazás lefagy vagy összeomlik. A Google Android Developer Blog szerint a felhasználók 70%-a törli az alkalmazást, ha az kétszer összeomlik vagy lefagy. Vizsgáljuk meg a kapcsolat elvesztésének okait és a hibatűrő kommunikáció kiépítésének módjait.
Főbb pontok
Megszakad — felhasználói kifejezés, amely azt a helyzetet írja le, amikor az alkalmazás elveszíti a kapcsolatot a szerverrel, nem reagál a műveletekre, vagy hibával fejeződik be. Technikai értelemben ez lehet: hálózati hiba (időtúllépés, DNS failure), ANR (UI szál blokkolása), crash (kezeletlen kivétel) vagy race condition (versenyhelyzet).
A felhasználó számára ezek a forgatókönyvek ugyanúgy néznek ki: az alkalmazás leáll. A fejlesztő számára a különbség a diagnosztika és a javítás megközelítésében rejlik. A hálózati hibák retry mechanizmusokkal oldhatók meg, az ANR a műveletek UI szálból való kiemelésével, a crash a kivételek kezelésével.
A Crittercism (ma Apteligent) szerint egy átlagos mobilalkalmazás a felhasználók 1-2%-át veszíti el minden egyes összeomláskor. Egy 1 millió felhasználós alkalmazás esetében ez 10-20 ezer elvesztett telepítést jelent hibánként. Ez különösen kritikus a pénzügyi és egészségügyi szektorban.
Instabil hálózat — a mobileszközök folyamatosan váltanak Wi-Fi és mobilhálózat között, lefedettség nélküli zónákba (metró, lift, pince) kerülnek. Minden váltás átmeneti kapcsolatvesztést okoz, amelyet az alkalmazásnak megfelelően kell kezelnie.
Időtúllépések — ha a szerver nem válaszol a beállított időn belül (általában 10-30 másodperc), a kliens SocketTimeoutException-t dob. A hosszú időtúllépések visszajelzés nélkül a felhasználó által lefagyásként érzékelhetők. Javasolt az időtúllépést legfeljebb 15 másodpercre beállítani.
val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build()
Versenyhelyzet (race condition) — akkor keletkezik, amikor több szál egyidejűleg olvassa és írja ugyanazokat az adatokat szinkronizálás nélkül. Például az adatok gyorsítótárból való betöltése a UI szálban párhuzamosan a gyorsítótár hálózatból való frissítésével elavult vagy helytelen adatok megjelenítéséhez vezethet.
Offline-first — architekturális minta, ahol a helyi tároló (Room, CoreData) az egyetlen igazságforrás. A hálózat a háttérben történő adatszinkronizáláshoz használatos. A felhasználó mindig naprakész adatokat lát a helyi gyorsítótárból, még hálózat hiányában is.
Repository pattern — egységes belépési pont az adatokhoz, amely eldönti, hogy az adatokat a hálózatból vagy a gyorsítótárból vegye-e. A repository elválasztja az adatforrást a ViewModel-től és a UI-tól. Hálózati hiba esetén a repository automatikusan átkapcsol a helyi forrásra.
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) // gyorsítótár visszaadása hálózati hibánál
} else {
Result.failure(e)
}
}
}
}
Circuit Breaker — a szerver védelmére szolgáló minta a kérések áradatától, amikor az nem elérhető. N egymást követő hiba után a megszakító kinyílik, és minden kérés azonnal hibát ad vissza kapcsolódási kísérlet nélkül. Egy meghatározott időtúllépés után a megszakító félnyitott állapotba kerül egy próbakéréshez.
Exponential backoff — standard retry mechanizmus. Az első sikertelenség után várjon 1 másodpercet, a második után 2 másodpercet, majd 4, 8, 16. Korlátozza a maximális próbálkozások számát (általában 3-5), hogy ne terhelje túl a szervert és az akkumulátort.
Felhasználói visszajelzés — hálózati hiba esetén jelenítsen meg érthető üzenetet: „Nincs kapcsolat”, „A szerver átmenetileg nem elérhető”, „Ellenőrizze az internetet”. Használjon Snackbar-t vagy Inline State View-t. Soha ne mutasson technikai hibákat (HTTP 500, SocketException) a felhasználónak.
ConnectivityManager — Android API a hálózat figyeléséhez. Engedje, hogy az alkalmazás reagáljon a változásokra: hálózat elvesztésekor jelenítsen meg placeholdert, helyreálláskor automatikusan frissítse az adatokat. iOS-ben használja a NWPathMonitor-t a Network keretrendszerből.
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) — standard összeomlás-jelentő eszköz mobilalkalmazásokhoz. Összegyűjti az összes kezeletlen kivétel stacktrace-ét, az operációs rendszer verzióját, az eszköz modelljét és az összeomlás idejét. Lehetővé teszi a hibák csoportosítását és a javításokért felelős személyek kijelölését.
Sentry — a Crashlytics alternatívája teljesítményfigyelő támogatással. Lehetővé teszi konkrét tranzakciók (pl. „felhasználó hitelesítése”) nyomon követését és annak megtekintését, hogy melyik lépésnél történt a hiba. Performance tracing segít megkülönböztetni a hálózati időtúllépéseket az alkalmazás logikájában lévő hibáktól.
Timber — naplózási könyvtár Androidhoz automatikus osztály szerinti címkék hozzáadásával. Debug buildben naplózza az összes hálózati kérést és választ. Release buildben — csak a hibákat és figyelmeztetésekat a Crashlytics.setCustomLog segítségével.
| Eszköz | Típus | Mikor használjuk |
|---|---|---|
| Crashlytics | Crash reporting | Mindig release-ben — automatikus összeomlásgyűjtés |
| Sentry | Crash + Performance | Amikor konkrét felhasználói forgatókönyveket kell profilozni |
| Timber | Logging | Debug: teljes naplózás; Release: csak hibák |
| HTTP Toolkit | Network debug | HTTP forgalom helyi elfogása és elemzése |
A Firebase Summit 2023 szerint azok az alkalmazások, amelyek bevezették a Crashlytics + Performance Monitoringot, a kritikus hibák észlelésének és javításának átlagos idejét 3 napról 4 órára csökkentik. Javasolt riasztást beállítani minden olyan összeomlásra, amelynek gyakorisága meghaladja az aktív felhasználók 0,1%-át.
Gyakran ismételt kérdések
Ha a crash nem fogható el a Crashlytics-ben, ellenőrizze a natív összeomlásokat (SIGSEGV, SIGABRT) — ezeket nem kezeli a Java/Kotlin kivételkezelő. Androidben ez lehet natív memóriaszivárgás JNI-ből, iOS-ben EXC_BAD_ACCESS. Használja a Breakpad (Android) vagy PLCrashReporter (iOS) eszközt a natív crash stacktrace összegyűjtéséhez.
Használja a Network Link Conditioner-t (beépítve iOS-ben, Androidhoz Facebook Network Connection Class vagy a Developer Options > Network > Select network type beállítások). Állítsa be a késleltetést 500-3000 ms-ra és a csomagvesztést 5-30%-ra. Használhatja továbbá a Charles Proxy-t vagy a mitmproxy-t a hálózati késleltetések és megszakítások szimulálására.
ANR akkor keletkezik, ha a UI szál 5 másodpercnél hosszabb ideig blokkolt. A hálózati kéréseket háttérszálon kell végrehajtani: coroutines (viewModelScope.launch(Dispatchers.IO)), RxJava (subscribeOn(Schedulers.io)) vagy WorkManager a szinkronizáláshoz. Mindig állítson be időtúllépést a HTTP kliensen — az időtúllépés hiánya örök blokkoláshoz vezethet.
Race condition — olyan helyzet, amikor a művelet eredménye a szálak végrehajtási sorrendjétől függ. Például a felhasználó gyorsan kétszer megnyomja a „Küldés” gombot, és a kérés kétszer kerül elküldésre. Megoldás: használjon Mutex-et, single-threaded executors-t vagy state machine-t (tiltsa le a gombot az első megnyomás után). Kotlinban használja a Mutex-et a coroutines-ből vagy a @Synchronized annotációt.
Alkalmazzon Chaos Engineering-et mobilalkalmazásokra: kapcsolja ki a hálózatot műveletek közben, szimuláljon nagy késleltetést, váltson Wi-Fi és mobilhálózat között, ölesse meg a folyamatot a rendszerrel. Eszközök: Facebook Network Connection Class, Charles Proxy, iOS Network Link Conditioner. CI/CD-ben adjon hozzá UI teszteket különböző hálózati körülményekkel az AndroidTest Orchestrator segítségével.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is