Verbindungsverlust — eines der häufigsten und frustrierendsten Phänomene in mobilen Apps. Der Benutzer verliert den Zugriff auf Daten, ein Vorgang wird unterbrochen, die App friert ein oder stürzt ab. Laut Google Android Developer Blog löschen 70% der Benutzer eine App, wenn sie zweimal abstürzt oder einfriert. Lassen Sie uns die Ursachen für Verbindungsverlust und Möglichkeiten zum Aufbau ausfallsicherer Kommunikation untersuchen.
Wichtige Punkte
Verbindungsabbruch — ein Benutzerbegriff, der eine Situation beschreibt, in der die App die Verbindung zum Server verliert, nicht mehr auf Aktionen reagiert oder mit einem Fehler beendet wird. Technisch gesehen kann dies sein: Netzwerkfehler (Zeitüberschreitung, DNS-Fehler), ANR (Einfrieren des UI-Threads), Absturz (unbehandelte Ausnahme) oder Race Condition.
Aus Benutzersicht sehen alle diese Szenarien gleich aus: Die App funktioniert nicht mehr. Der Unterschied für Entwickler liegt im Diagnose- und Korrekturansatz. Netzwerkfehler werden mit Wiederholungsmechanismen gelöst, ANR durch Auslagern von Operationen aus dem UI-Thread, Abstürze durch Ausnahmebehandlung.
Laut Crittercism (jetzt Apteligent) verliert eine mobile App im Durchschnitt 1–2% ihrer Benutzer bei jedem Absturz. Für eine App mit 1 Million Benutzern bedeutet dies 10–20.000 verlorene Installationen pro einzelnen Fehler. Besonders kritisch ist dies für Apps im Finanz- und Medizinsektor.
Instabiles Netzwerk — mobile Geräte wechseln ständig zwischen WLAN und Mobilfunknetz und betreten Bereiche ohne Abdeckung (U-Bahn, Aufzug, Keller). Jeder Wechsel verursacht einen vorübergehenden Verbindungsverlust, den die App korrekt behandeln muss.
Zeitüberschreitungen — wenn der Server nicht innerhalb des festgelegten Timeouts (normalerweise 10–30 Sekunden) antwortet, wirft der Client eine SocketTimeoutException. Lange Timeouts ohne Rückmeldung werden vom Benutzer als Einfrieren wahrgenommen. Es wird empfohlen, ein Timeout von nicht mehr als 15 Sekunden einzustellen.
val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build()
Race Condition — tritt auf, wenn mehrere Threads gleichzeitig dieselben Daten ohne Synchronisation lesen und schreiben. Beispielsweise kann das Laden von Daten aus dem Cache im UI-Thread bei gleichzeitiger Aktualisierung des Caches aus dem Netzwerk zur Anzeige veralteter oder falscher Daten führen.
Offline-first — ein Architekturmuster, bei dem der lokale Speicher (Room, CoreData) die einzige Quelle der Wahrheit ist. Das Netzwerk wird zur Datensynchronisation im Hintergrund verwendet. Der Benutzer sieht immer aktuelle Daten aus dem lokalen Cache, auch ohne Netzwerkverbindung.
Repository-Muster — ein einzelner Einstiegspunkt für Daten, der entscheidet, ob Daten aus dem Netzwerk oder aus dem Cache geholt werden. Das Repository abstrahiert die Datenquelle vom ViewModel und der UI. Bei einem Netzwerkfehler wechselt das Repository automatisch zur lokalen Quelle.
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 — ein Muster, das den Server vor einer Flut von Anfragen schützt, wenn er nicht verfügbar ist. Nach N aufeinanderfolgenden Fehlern öffnet sich der Trennschalter, und alle Anfragen geben sofort einen Fehler zurück, ohne eine Verbindung zu versuchen. Nach einem bestimmten Timeout wechselt der Trennschalter für eine Testanfrage in den halboffenen Zustand.
Exponentielles Backoff — ein standardmäßiger Wiederholungsmechanismus. Nach dem ersten Fehler 1 Sekunde warten, nach dem zweiten 2 Sekunden, dann 4, 8, 16. Begrenzen Sie die maximale Anzahl der Wiederholungsversuche (normalerweise 3–5), um Server und Akku nicht zu überlasten.
Benutzerfeedback — zeigen Sie bei einem Netzwerkfehler eine klare Nachricht an: „Keine Verbindung“, „Server vorübergehend nicht verfügbar“, „Überprüfen Sie Ihre Internetverbindung“. Verwenden Sie Snackbar oder Inline State View. Zeigen Sie dem Benutzer niemals technische Fehler (HTTP 500, SocketException) an.
ConnectivityManager — Android-API zur Netzwerküberwachung. Ermöglichen Sie der App, auf Änderungen zu reagieren: bei Verbindungsverlust einen Platzhalter anzeigen, bei Wiederherstellung automatisch Daten aktualisieren. Verwenden Sie unter iOS NWPathMonitor aus dem Network-Framework.
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) — ein Standardwerkzeug zur Absturzberichterstattung für mobile Apps. Es sammelt Stacktraces aller unbehandelten Ausnahmen, OS-Version, Gerätemodell und Absturzzeit. Es ermöglicht die Gruppierung von Fehlern und die Zuweisung von Verantwortlichen für Korrekturen.
Sentry — eine Alternative zu Crashlytics mit Unterstützung für Leistungsüberwachung. Es ermöglicht die Verfolgung bestimmter Transaktionen (z.B. „Benutzerautorisierung“) und die Anzeige, bei welchem Schritt ein Fehler aufgetreten ist. Leistungsverfolgung hilft, Netzwerkzeitüberschreitungen von Fehlern in der App-Logik zu unterscheiden.
Timber — eine Protokollierungsbibliothek für Android mit automatischer Hinzufügung von Tags nach Klasse. In Debug-Builds protokollieren Sie alle Netzwerkanfragen und -antworten. In Release-Builds protokollieren Sie nur Fehler und Warnungen über Crashlytics.setCustomLog.
| Werkzeug | Typ | Wann verwenden |
|---|---|---|
| Crashlytics | Absturzberichterstattung | Immer im Release — automatische Absturzerfassung |
| Sentry | Absturz + Leistung | Wenn Sie bestimmte Benutzerszenarien profilieren müssen |
| Timber | Protokollierung | Debug: vollständige Protokollierung; Release: nur Fehler |
| HTTP Toolkit | Netzwerk-Debug | Lokale HTTP-Datenverkehrsabfang und -Analyse |
Laut Firebase Summit 2023 reduzieren Apps, die Crashlytics + Performance Monitoring implementiert haben, die durchschnittliche Zeit zur Erkennung und Behebung kritischer Fehler von 3 Tagen auf 4 Stunden. Es wird empfohlen, Warnungen für jeden Absturz mit einer Häufigkeit von mehr als 0,1% der aktiven Benutzer einzurichten.
Häufig gestellte Fragen
Wenn ein Absturz in Crashlytics nicht erfasst wird, überprüfen Sie native Abstürze (SIGSEGV, SIGABRT) — sie werden nicht vom Java/Kotlin-Ausnahmehandler behandelt. In Android könnte dies ein nativer Speicherverlust aus JNI sein, in iOS EXC_BAD_ACCESS. Verwenden Sie Breakpad (Android) oder PLCrashReporter (iOS), um native Absturz-Stacktraces zu sammeln.
Verwenden Sie Network Link Conditioner (in iOS integriert; für Android verwenden Sie Facebook Network Connection Class oder Developer Options > Network > Select network type). Stellen Sie eine Verzögerung von 500–3000 ms und einen Paketverlust von 5–30% ein. Sie können auch Charles Proxy oder mitmproxy verwenden, um Netzwerklatenz und Verbindungsabbrüche zu simulieren.
ANR tritt auf, wenn der UI-Thread länger als 5 Sekunden blockiert ist. Netzwerkanfragen sollten in einem Hintergrundthread ausgeführt werden: Coroutinen (viewModelScope.launch(Dispatchers.IO)), RxJava (subscribeOn(Schedulers.io)), oder WorkManager zur Synchronisation. Setzen Sie immer Timeouts auf dem HTTP-Client — ein fehlendes Timeout kann zu dauerhafter Blockierung führen.
Race Condition — eine Situation, in der das Ergebnis einer Operation von der Reihenfolge der Thread-Ausführung abhängt. Zum Beispiel drückt ein Benutzer schnell zweimal die „Senden“-Taste und die Anfrage wird zweimal gesendet. Lösung: Verwenden Sie Mutex, Single-Thread-Executors oder eine Zustandsmaschine (deaktivieren Sie die Schaltfläche nach dem ersten Klick). In Kotlin verwenden Sie Mutex aus Coroutinen oder die @Synchronized-Annotation.
Wenden Sie Chaos Engineering für mobile Apps an: trennen Sie das Netzwerk während Operationen, simulieren Sie hohe Latenz, wechseln Sie zwischen WLAN und Mobilfunknetz, beenden Sie den Prozess über das System. Werkzeuge: Facebook Network Connection Class, Charles Proxy, iOS Network Link Conditioner. Fügen Sie in CI/CD UI-Tests mit verschiedenen Netzwerkbedingungen über AndroidTest Orchestrator hinzu.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch