Αποσυνδέεται — τι είναι, τυπικές αιτίες και μέθοδοι επίλυσης

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-07-29 Χρόνος ανάγνωσης: 10 λεπ

Απώλεια σύνδεσης — ένα από τα πιο συνηθισμένα και ενοχλητικά φαινόμενα στις εφαρμογές κινητών. Ο χρήστης χάνει την πρόσβαση σε δεδομένα, η λειτουργία διακόπτεται, η εφαρμογή παγώνει ή κολλάει. Σύμφωνα με το Google Android Developer Blog, το 70% των χρηστών διαγράφει την εφαρμογή αν κολλήσει ή παγώσει δύο φορές. Ας αναλύσουμε τις αιτίες απώλειας σύνδεσης και τους τρόπους δημιουργίας ανθεκτικών επικοινωνιών.

Κύρια σημεία

  • ANR (Application Not Responding) — μπλοκάρισμα του νήματος UI για περισσότερο από 5 δευτερόλεπτα οδηγεί σε αναγκαστικό τερματισμό
  • Offline-first — αρχιτεκτονική όπου η τοπική αποθήκευση είναι η πηγή αλήθειας και το δίκτυο ο μηχανισμός συγχρονισμού
  • Retry with backoff — αυτόματη επανάληψη αιτήματος με αυξανόμενη καθυστέρηση σε σφάλματα δικτύου
  • ConnectivityManager — Android API για παρακολούθηση της κατάστασης δικτύου και προσαρμογή συμπεριφοράς εφαρμογής
  • Graceful degradation — η εφαρμογή πρέπει να λειτουργεί (τουλάχιστον εν μέρει) απουσία δικτύου

Τι σημαίνει «αποσυνδέεται» στις εφαρμογές κινητών;

Αποσυνδέεται — όρος χρήστη που περιγράφει την κατάσταση όταν η εφαρμογή χάνει τη σύνδεση με τον διακομιστή, σταματά να ανταποκρίνεται σε ενέργειες ή τερματίζεται με σφάλμα. Από τεχνική άποψη μπορεί να είναι: σφάλμα δικτύου (timeout, DNS failure), ANR (μπλοκάρισμα νήματος UI), crash (μη διαχειριζόμενη εξαίρεση) ή race condition (συνθήκη ανταγωνισμού).

Για τον χρήστη όλα αυτά τα σενάρια φαίνονται ίδια: η εφαρμογή σταματά να λειτουργεί. Η διαφορά για τον προγραμματιστή βρίσκεται στην προσέγγιση διάγνωσης και επιδιόρθωσης. Τα σφάλματα δικτύου λύνονται με μηχανισμούς retry, το ANR με μεταφορά λειτουργιών εκτός νήματος UI, το crash με διαχείριση εξαιρέσεων.

Σύμφωνα με την Crittercism (τώρα Apteligent), μια μέση εφαρμογή κινητού χάνει 1-2% των χρηστών της σε κάθε κολλάρισμα. Για μια εφαρμογή με 1 εκατομμύριο χρήστες, αυτό σημαίνει 10-20 χιλιάδες χαμένες εγκαταστάσεις ανά σφάλμα. Αυτό είναι ιδιαίτερα κρίσιμο για εφαρμογές στον χρηματοοικονομικό και ιατρικό τομέα.

Κύριες αιτίες απώλειας σύνδεσης

Ασταθές δίκτυο — οι κινητές συσκευές εναλλάσσονται συνεχώς μεταξύ Wi-Fi και κινητού δικτύου, εισέρχονται σε ζώνες χωρίς κάλυψη (μετρό, ασανσέρ, υπόγειο). Κάθε εναλλαγή προκαλεί προσωρινή απώλεια σύνδεσης που η εφαρμογή πρέπει να χειριστεί σωστά.

Χρονικά όρια — αν ο διακομιστής δεν αποκριθεί εντός του καθορισμένου χρόνου (συνήθως 10-30 δευτερόλεπτα), ο πελάτης εκτοξεύει SocketTimeoutException. Τα μεγάλα χρονικά όρια χωρίς ανάδραση γίνονται αντιληπτά από τον χρήστη ως πάγωμα. Συνιστάται η ρύθμιση χρονικού ορίου όχι μεγαλύτερου από 15 δευτερόλεπτα.

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

Συνθήκη ανταγωνισμού (race condition) — προκύπτει όταν πολλαπλά νήματα διαβάζουν και γράφουν ταυτόχρονα τα ίδια δεδομένα χωρίς συγχρονισμό. Για παράδειγμα, η φόρτωση δεδομένων από την προσωρινή μνήμη στο νήμα UI παράλληλα με την ενημέρωση της προσωρινής μνήμης από το δίκτυο μπορεί να οδηγήσει στην εμφάνιση παλαιών ή εσφαλμένων δεδομένων.

  • Μη διαχειριζόμενες εξαιρέσεις σε callback ή coroutine οδηγούν σε κολλάρισμα της εφαρμογής
  • Πίεση μνήμης — το σύστημα σκοτώνει την εφαρμογή όταν υπάρχει έλλειψη μνήμης για την εφαρμογή προσκηνίου
  • Lifecycle race — η ασύγχρονη λειτουργία ολοκληρώνεται αφού το Activity/Fragment έχει καταστραφεί
  • Μπλοκάρισμα UI — η εκτέλεση δικτύου ή βάσης δεδομένων στο κύριο νήμα προκαλεί ANR μετά από 5 δευτερόλεπτα

Αρχιτεκτονική για ανθεκτικές εφαρμογές

Offline-first — αρχιτεκτονικό μοτίβο όπου η τοπική αποθήκευση (Room, CoreData) είναι η μοναδική πηγή αλήθειας. Το δίκτυο χρησιμοποιείται για συγχρονισμό δεδομένων στο παρασκήνιο. Ο χρήστης βλέπει πάντα ενημερωμένα δεδομένα από την τοπική προσωρινή μνήμη, ακόμα και απουσία δικτύου.

Repository pattern — ενιαίο σημείο εισόδου για δεδομένα που αποφασίζει αν θα λάβει δεδομένα από το δίκτυο ή από την προσωρινή μνήμη. Το αποθετήριο αφαιρεί την πηγή δεδομένων από το ViewModel και το UI. Σε σφάλμα δικτύου, το αποθετήριο μεταβαίνει αυτόματα στην τοπική πηγή.

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) // επιστροφή προσωρινής μνήμης σε σφάλμα δικτύου
            } else {
                Result.failure(e)
            }
        }
    }
}

Circuit Breaker — μοτίβο προστασίας του διακομιστή από χείμαρρο αιτημάτων όταν είναι μη διαθέσιμος. Μετά από N διαδοχικά σφάλματα, ο διακόπτης ανοίγει και όλα τα αιτήματα επιστρέφουν αμέσως σφάλμα χωρίς προσπάθεια σύνδεσης. Μετά από καθορισμένο χρονικό όριο, ο διακόπτης μεταβαίνει σε μισάνοιχτη κατάσταση για δοκιμαστικό αίτημα.

Πώς να χειρίζεστε σφάλματα δικτύου;

Exponential backoff — τυπικός μηχανισμός retry. Μετά την πρώτη αποτυχία περιμένετε 1 δευτερόλεπτο, μετά τη δεύτερη — 2 δευτερόλεπτα, στη συνέχεια 4, 8, 16. Περιορίστε τον μέγιστο αριθμό προσπαθειών (συνήθως 3-5) για να μην υπερφορτώνετε τον διακομιστή και την μπαταρία.

Ανάδραση χρήστη — σε σφάλμα δικτύου εμφανίστε ένα κατανοητό μήνυμα: „Δεν υπάρχει σύνδεση”, „Ο διακομιστής είναι προσωρινά μη διαθέσιμος”, „Ελέγξτε το διαδίκτυο”. Χρησιμοποιήστε Snackbar ή Inline State View. Ποτέ μην εμφανίζετε τεχνικά σφάλματα (HTTP 500, SocketException) στον χρήστη.

ConnectivityManager — Android API για παρακολούθηση δικτύου. Επιτρέψτε στην εφαρμογή να αντιδρά σε αλλαγές: σε απώλεια δικτύου εμφανίστε placeholder, σε αποκατάσταση — ενημερώστε αυτόματα τα δεδομένα. Στο iOS χρησιμοποιήστε το NWPathMonitor από το πλαίσιο 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)
    }
}

Εργαλεία παρακολούθησης και καταγραφής

Crashlytics (Firebase) — τυπικό εργαλείο αναφοράς κολλαρισμάτων για εφαρμογές κινητών. Συλλέγει stacktrace όλων των μη διαχειριζόμενων εξαιρέσεων, έκδοση λειτουργικού συστήματος, μοντέλο συσκευής και χρόνο κολλαρίσματος. Επιτρέπει την ομαδοποίηση σφαλμάτων και την ανάθεση υπευθύνων για διορθώσεις.

Sentry — εναλλακτική του Crashlytics με υποστήριξη παρακολούθησης απόδοσης. Επιτρέπει την ανίχνευση συγκεκριμένων συναλλαγών (π.χ. „ταυτοποίηση χρήστη”) και την προβολή σε ποιο βήμα συνέβη το σφάλμα. Performance tracing βοηθά στη διάκριση χρονικών ορίων δικτύου από σφάλματα στη λογική της εφαρμογής.

Timber — βιβλιοθήκη καταγραφής για Android με αυτόματη προσθήκη ετικετών ανά κλάση. Σε debug build καταγράφετε όλα τα αιτήματα και αποκρίσεις δικτύου. Σε release build — μόνο σφάλματα και προειδοποιήσεις μέσω Crashlytics.setCustomLog.

ΕργαλείοΤύποςΠότε να χρησιμοποιείται
CrashlyticsCrash reportingΠάντα σε release — αυτόματη συλλογή κολλαρισμάτων
SentryCrash + PerformanceΌταν χρειάζεται προφίλ συγκεκριμένων σεναρίων χρήστη
TimberLoggingDebug: πλήρης καταγραφή; Release: μόνο σφάλματα
HTTP ToolkitNetwork debugΤοπική υποκλοπή και ανάλυση κίνησης HTTP

Σύμφωνα με το Firebase Summit 2023, οι εφαρμογές που εφάρμοσαν Crashlytics + Performance Monitoring μειώνουν τον μέσο χρόνο ανίχνευσης και επιδιόρθωσης κρίσιμων σφαλμάτων από 3 ημέρες σε 4 ώρες. Συνιστάται η ρύθμιση ειδοποιήσεων για κάθε κολλάρισμα με συχνότητα μεγαλύτερη από 0,1% των ενεργών χρηστών.

Συχνές ερωτήσεις

Τι να κάνετε αν η εφαρμογή κολλάει χωρίς μήνυμα σφάλματος;

Αν το crash δεν πιάνεται στο Crashlytics, ελέγξτε το native crash (SIGSEGV, SIGABRT) — δεν τα επεξεργάζεται ο χειριστής εξαιρέσεων Java/Kotlin. Στο Android αυτό μπορεί να είναι διαρροή native μνήμης από JNI, στο iOS — EXC_BAD_ACCESS. Χρησιμοποιήστε Breakpad (Android) ή PLCrashReporter (iOS) για συλλογή stacktrace native crash.

Πώς να αναπαράγετε ένα σφάλμα που εμφανίζεται μόνο σε αδύναμο δίκτυο;

Χρησιμοποιήστε Network Link Conditioner (ενσωματωμένο στο iOS, για Android υπάρχει Facebook Network Connection Class ή ρυθμίσεις Developer Options > Network > Select network type). Ρυθμίστε καθυστέρηση 500-3000 ms και απώλεια πακέτων 5-30%. Μπορείτε επίσης να χρησιμοποιήσετε Charles Proxy ή mitmproxy για εξομοίωση καθυστερήσεων δικτύου και αποσυνδέσεων.

Πώς να αποτρέψετε το ANR σε αιτήματα δικτύου;

ANR προκύπτει όταν το νήμα UI είναι μπλοκαρισμένο για περισσότερο από 5 δευτερόλεπτα. Τα αιτήματα δικτύου πρέπει να εκτελούνται σε νήμα παρασκηνίου: coroutines (viewModelScope.launch(Dispatchers.IO)), RxJava (subscribeOn(Schedulers.io)) ή WorkManager για συγχρονισμό. Πάντα να ορίζετε χρονικά όρια στον πελάτη HTTP — η απουσία χρονικού ορίου μπορεί να οδηγήσει σε αιώνιο μπλοκάρισμα.

Τι είναι το race condition και πώς να το αποφύγετε;

Race condition — κατάσταση όπου το αποτέλεσμα μιας λειτουργίας εξαρτάται από τη σειρά εκτέλεσης των νημάτων. Για παράδειγμα, ο χρήστης πατά γρήγορα δύο φορές το κουμπί „Αποστολή” και το αίτημα αποστέλλεται δύο φορές. Λύση: χρησιμοποιήστε Mutex, single-threaded executors ή state machine (απενεργοποιήστε το κουμπί μετά το πρώτο πάτημα). Στο Kotlin χρησιμοποιήστε Mutex από coroutines ή τη σημείωση @Synchronized.

Πώς να δοκιμάσετε την ανθεκτικότητα της εφαρμογής;

Εφαρμόστε Chaos Engineering για εφαρμογές κινητών: απενεργοποιήστε το δίκτυο κατά τη διάρκεια λειτουργιών, προσομοιώστε υψηλή καθυστέρηση, εναλλάξτε μεταξύ Wi-Fi και κινητού δικτύου, σκοτώστε τη διεργασία από το σύστημα. Εργαλεία: Facebook Network Connection Class, Charles Proxy, iOS Network Link Conditioner. Στο CI/CD προσθέστε δοκιμές UI με διαφορετικές συνθήκες δικτύου μέσω AndroidTest Orchestrator.

Σύνοψη

  • Αποσυνδέεται — συλλογικός όρος για σφάλματα δικτύου, ANR, crash και race conditions; η εμπειρία χρήστη είναι ίδια, οι αιτίες διαφορετικές
  • Σφάλματα δικτύου — η πιο συχνή αιτία; η λύση περιλαμβάνει χρονικά όρια (10-15 δευτερόλεπτα), exponential backoff και αρχιτεκτονική offline-first
  • ANR προκύπτει από μπλοκάρισμα του νήματος UI για περισσότερο από 5 δευτερόλεπτα; οι λειτουργίες δικτύου και δίσκου να εκτελούνται πάντα σε νήμα παρασκηνίου
  • Offline-first με Repository pattern: τοπική αποθήκευση — πηγή αλήθειας, δίκτυο — μηχανισμός συγχρονισμού
  • Crashlytics + Performance Monitoring — ελάχιστο σετ για παρακολούθηση παραγωγής με ειδοποιήσεις σε συχνά κολλαρίσματα
  • Συνθήκη ανταγωνισμού απαιτεί συγχρονισμό νημάτων: Mutex, State Machine ή μονονηματικό εκτελεστή
  • Δοκιμάστε με εξομοίωση αδύναμου δικτύου και Chaos Engineering — μόνο έτσι μπορείτε να ανακαλύψετε προβλήματα κρυμμένα σε ιδανικές συνθήκες ανάπτυξης

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης