onStop — τι είναι, απόκρυψη Activity στον κύκλο ζωής του Android

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

onStop — μέθοδος του κύκλου ζωής Activity στο Android, που καλείται από το σύστημα όταν το Activity παύει να είναι ορατό στον χρήστη. Το Activity μεταβαίνει στην κατάσταση Stopped αφού ένα νέο Activity το καλύψει πλήρως, ή κατά την ελαχιστοποίηση της εφαρμογής. Στη μέθοδο onStop, ο προγραμματιστής είναι υποχρεωμένος να σταματήσει τα κινούμενα σχέδια, να ελευθερώσει τους πόρους της κάμερας και των αισθητήρων, να αποθηκεύσει τα πρόχειρα των δεδομένων που εισήχθησαν. Σύμφωνα με το Android Vitals (Google, 2025), η σωστή διαχείριση του onStop μειώνει τον αριθμό ANR (Application Not Responding) κατά την ελαχιστοποίηση της εφαρμογής κατά 35%. Μετά το onStop, το σύστημα μπορεί να καλέσει onRestart (επιστροφή στην οθόνη) ή onDestroy (πλήρης τερματισμός). Η τεκμηρίωση Android Developers για τον κύκλο ζωής Activity περιγράφει το onStop ως το όριο μεταξύ ορατής και αόρατης κατάστασης.

Κύρια σημεία

  • onStop — μέθοδος που καλείται όταν το Activity χάνει εντελώς την ορατότητα, αλλά το Activity βρίσκεται ακόμα στη μνήμη.
  • Μετά το onStop, το Activity μεταβαίνει στην κατάσταση Stopped — ζωντανό στη μνήμη, αλλά δεν είναι ορατό και δεν αλληλεπιδρά με τον χρήστη.
  • Το σύστημα μπορεί να καλέσει onRestart → onStart → onResume κατά την επιστροφή στο Activity ή onDestroy κατά τον τερματισμό.
  • Στο onStop πρέπει να ελευθερωθούν πόροι: να σταματήσουν τα κινούμενα σχέδια, να απενεργοποιηθούν οι αισθητήρες και η κάμερα, να αποθηκευτούν προσωρινά δεδομένα.
  • Η σωστή υλοποίηση του onStop — βασικός παράγοντας σταθερότητας της εφαρμογής σε πολλαπλές εργασίες και ελαχιστοποίηση.

Τι είναι το onStop στο Android;

onStop — είναι μια μέθοδος callback της κλάσης AppCompatActivity (και του προκατόχου της Activity), η οποία καλείται από το λειτουργικό σύστημα Android όταν το Activity παύει να είναι εντελώς ορατό στον χρήστη. Αυτή τη στιγμή, το Activity κρύβεται από άλλο Activity, παράθυρο διαλόγου, εκκινητή συστήματος ή οθόνη κλειδώματος. Από την άποψη του κύκλου ζωής, το onStop ακολουθεί το onPause και σηματοδοτεί ότι το Activity δεν είναι πλέον ορατό στην οθόνη, αν και το ίδιο το αντικείμενο Activity και η κατάστασή του παραμένουν στη μνήμη.

Όταν το Activity μεταβαίνει στην κατάσταση Stopped (σταματημένο), διατηρεί την κατάστασή του στη μνήμη RAM — όλα τα πεδία, η ιεραρχία View και το ViewModel παραμένουν προσβάσιμα. Αυτό διαφοροποιεί το Stopped από την κατεστραμμένη (Destroyed) κατάσταση, όπου το Activity αφαιρείται εντελώς. Το System UI μπορεί να σκοτώσει τη διεργασία της εφαρμογής που βρίσκεται σε κατάσταση Stopped σε περίπτωση έλλειψης μνήμης — αυτό ονομάζεται process death. Ο προγραμματιστής είναι υποχρεωμένος να αποθηκεύσει κρίσιμα δεδομένα (πρόχειρα, θέση κύλισης) στο onSaveInstanceState(), το οποίο καλείται πριν από το onStop, για να εγγυηθεί την επαναφορά κατά τη διακοπή της διεργασίας.

Σύμφωνα με τις προδιαγραφές Android Compatibility Definition Document (CDD) για την έκδοση 14+, η διεργασία σε κατάσταση Stopped έχει χαμηλότερη προτεραιότητα κατά τη διακοπή από το OOM Killer — χαμηλότερη από τις διεργασίες στη φάση Background, αλλά υψηλότερη από τις προσωρινά αποθηκευμένες διεργασίες. Σύμφωνα με στατιστικά της Google, το 68% των περιπτώσεων διακοπής διεργασιών συμβαίνει όταν το Activity βρίσκεται σε κατάσταση Stopped, όχι Paused.

Πότε καλείται το onStop: σενάρια και σειρά

Το onStop καλείται όταν το Activity χάνει εντελώς την ορατότητα, ανεξάρτητα από την αιτία: εκκίνηση νέου Activity πάνω από το τρέχον, ελαχιστοποίηση της εφαρμογής (πάτημα Home), κλείδωμα οθόνης, εισερχόμενη κλήση ή άνοιγμα συστήματος διαλόγου. Σε όλες αυτές τις περιπτώσεις, το Activity λαμβάνει πρώτα onPause (μερική απώλεια εστίασης) και στη συνέχεια onStop (πλήρης απώλεια ορατότητας).

Βασικά σενάρια κλήσης onStop:

  • Εκκίνηση νέου Activity πάνω από το τρέχον — το τρέχον Activity λαμβάνει onPause, στη συνέχεια onStop; το νέο Activity περνά από onCreate → onStart → onResume.
  • Ελαχιστοποίηση εφαρμογής (Home) — το Activity μεταβαίνει σε onPause → onStop εντός 200–300 ms, παραμένει στη μνήμη σε κατάσταση Stopped.
  • Κλείδωμα οθόνης — το σύστημα καλεί onPause → onStop, επειδή η οθόνη κλειδώματος καλύπτει πλήρως το Activity.
  • Εισερχόμενη κλήση — το Activity τηλεφώνου (Dialer) εκκινείται από πάνω, το τρέχον Activity μεταβαίνει σε onStop.
  • Εναλλαγή σε άλλη εφαρμογή (Recent Apps) — το Activity κρύβεται, λαμβάνει onStop, αλλά παραμένει στην προσωρινή μνήμη διεργασιών.

Είναι σημαντικό να κατανοήσετε ότι το onStop δεν καλείται κατά την περιστροφή της οθόνης — σε αυτήν την περίπτωση, το Activity καταστρέφεται (onPause → onStop → onDestroy) και δημιουργείται ξανά (onCreate → onStart → onResume). Εξαίρεση — η σημαία android:configChanges="orientation" στο manifest, όπου το Activity δεν αναδημιουργείται, αλλά λαμβάνει την κλήση onConfigurationChanged().

onStop στον κύκλο ζωής Activity

Το onStop κατέχει κεντρική θέση στη σειρά του κύκλου ζωής Activity μεταξύ ορατής και αόρατης κατάστασης. Πλήρης σειρά: onCreate → onStart → onResume → (ενεργή κατάσταση) → onPause → onStop → onDestroy (ή onRestart → onStart → onResume κατά την επιστροφή).

ΚατάστασηΜέθοδοςΟρατότηταΑλληλεπίδρασηΜνήμη
CreatedonCreateΌχιΌχιΕκχωρείται
StartedonStartΜερικήΌχιΠλήρης
ResumedonResumeΠλήρηςΝαιΠλήρης
PausedonPauseΜερικήΌχιΠλήρης
StoppedonStopΌχιΌχιΠλήρης*
DestroyedonDestroyΌχιΌχιΕλευθερώθηκε

*Στην κατάσταση Stopped, το Activity διατηρείται στη μνήμη, αλλά μπορεί να σκοτωθεί από το σύστημα σε περίπτωση έλλειψης πόρων. Προτεραιότητα διακοπής διεργασιών Stopped — προτελευταία, υψηλότερη μόνο από κενές προσωρινά αποθηκευμένες διεργασίες.

onStop και onSaveInstanceState: Το σύστημα καλεί onSaveInstanceState(Bundle) πριν από το onStop για να αποθηκεύσει τη δυναμική κατάσταση UI. Ο προγραμματιστής παρακάμπτει αυτήν τη μέθοδο για να αποθηκεύσει στο Bundle τις τιμές των πεδίων εισόδου, τη θέση RecyclerView, τα επιλεγμένα στοιχεία. Ακόμα κι αν το Activity δεν καταστραφεί (ο χρήστης απλώς την ελαχιστοποίησε και επέστρεψε), το Bundle μεταβιβάζεται στο onCreate σε αλλαγές διαμόρφωσης. Η Google συνιστά να αποθηκεύετε μόνο προσωρινή κατάσταση UI — όχι δεδομένα αποθετηρίου ή ViewModel που ζουν εκτός Activity.

Ποιους πόρους να ελευθερώσετε στο onStop

Στο onStop, ο προγραμματιστής είναι υποχρεωμένος να ελευθερώσει όλους τους πόρους που δεν χρειάζονται όταν το Activity δεν είναι ορατό. Αυτό μειώνει την επιβάρυνση της μπαταρίας, του επεξεργαστή και της μνήμης, και αποτρέπει το ANR κατά την επιστροφή στη δραστηριότητα.

Τι να ελευθερώσετε στο onStop:

  • Κινούμενα σχέδια και transitions — σταματήστε ObjectAnimator, ValueAnimator, ViewPropertyAnimator. Ένα κινούμενο σχέδιο που εκτελείται σε αόρατο Activity είναι σπατάλη κύκλων GPU.
  • Αισθητήρες (Sensors) — διαγραφείτε από το SensorManager (επιταχυνσιόμετρο, γυροσκόπιο, μαγνητόμετρο). Οι αισθητήρες καταναλώνουν ενέργεια ακόμα και όταν το Activity είναι κρυφό.
  • Κάμερα και μικρόφωνο — ελευθερώστε Camera2 ή CameraX, σταματήστε MediaRecorder. Το να αφήνετε την κάμερα ενεργή σε κρυφό Activity απαγορεύεται από την πολιτική Google Play.
  • LocationListener — διαγραφείτε από FusedLocationProviderClient ή LocationManager. Η γεωτοποθεσία είναι ο πιο ενεργοβόρος πόρος.
  • Network listeners — κλείστε WebSocket, ακυρώστε αιτήματα HTTP που δεν χρειάζονται στο παρασκήνιο.
  • MediaPlayer και ExoPlayer — θέστε σε παύση ή σταματήστε εάν η αναπαραγωγή δεν πρέπει να συνεχιστεί στο παρασκήνιο.

Τι να μην κάνετε στο onStop: Μην εκτελείτε μεγάλες λειτουργίες — αποθήκευση μεγάλων δεδομένων στη βάση, αιτήματα δικτύου, περίπλοκους υπολογισμούς. Το onStop εκτελείται στο κύριο νήμα και μπλοκάρει την επιστροφή στο Activity. Για μεγάλες λειτουργίες, χρησιμοποιήστε WorkManager με καθυστέρηση ή coroutines στο viewModelScope. Μην ελευθερώνετε πόρους ViewModel — το ViewModel επιβιώνει από το onStop και θα χρησιμοποιηθεί κατά την επιστροφή.

Διαφορά μεταξύ onStop και onPause

Τα onPause και onStop διαφέρουν ως προς τον βαθμό απώλειας ορατότητας και τον όγκο των υποχρεωτικών ενεργειών. Το onPause καλείται σε μερική απώλεια εστίασης (για παράδειγμα, άνοιγμα παραθύρου διαλόγου ή μενού συστήματος), το onStop — σε πλήρη απώλεια ορατότητας. Αυτή η διαφορά είναι σημαντική για την επιλογή των πόρων που θα ελευθερωθούν σε κάθε στάδιο.

ΧαρακτηριστικόonPauseonStop
Βαθμός ορατότηταςΜερικώς ορατόΕντελώς αόρατο
ΕστίασηΧάθηκεΧάθηκε
Χρόνος εκτέλεσηςΈως 500 msΈως 5 δευτ. (ANR timeout)
Πόροι προς ελευθέρωσηΚρίσιμοι (μέσα, κάμερα)Όλοι αόρατοι (αισθητήρες, κινούμενα σχέδια, location)
ΑποκατάστασηonResumeonRestart → onStart → onResume
Προτεραιότητα διεργασίαςΥψηλή (Foreground)Μεσαία (Background)

Γενικός κανόνας: στο onPause, ελευθερώστε πόρους συστήματος που άμεσα επηρεάζουν την εμπειρία χρήστη άλλης εφαρμογής (κάμερα, πρόγραμμα αναπαραγωγής μέσων), στο onStop — όλους τους άλλους πόρους που δεν χρειάζονται όταν το Activity είναι κρυφό. Η Google συνιστά στο onPause να αποθηκεύετε κρίσιμα δεδομένα χρήστη (πρόχειρο email, ρυθμίσεις), καθώς το onStop μπορεί να μην συμβεί κατά τη γρήγορη εναλλαγή.

onStop → onRestart: επιστροφή στην οθόνη

Όταν ο χρήστης επιστρέφει στο κρυφό Activity, το σύστημα καλεί onRestart → onStart → onResume. Η μέθοδος onRestart σηματοδοτεί ότι το Activity επιστρέφει από την κατάσταση Stopped. Αυτό είναι ένα σημαντικό στάδιο για την αποκατάσταση UI και πόρων που ελευθερώθηκαν στο onStop.

Σειρά κλήσεων κατά την επιστροφή:

  • onRestart() — το Activity ειδοποιείται ότι θα εμφανιστεί ξανά. Τυπικές ενέργειες: επαναφόρτωση δεδομένων, ενημέρωση λιστών.
  • onStart() — το Activity γίνεται ορατό, αλλά δεν είναι ακόμα ενεργό. Εδώ οι πόροι που ελευθερώθηκαν στο onStop επαναρχικοποιούνται.
  • onResume() — το Activity λαμβάνει εστίαση και είναι έτοιμο για αλληλεπίδραση. Τα κινούμενα σχέδια ξεκινούν, οι αισθητήρες καταγράφονται.

Εάν η διεργασία της εφαρμογής σκοτώθηκε από το σύστημα σε κατάσταση Stopped, το onCreate καλείται αντί για onRestart, και το Bundle από το onSaveInstanceState μεταβιβάζεται για επαναφορά της κατάστασης. Αυτό το σενάριο (process death) — μία από τις πιο συχνές αιτίες σφαλμάτων σε εφαρμογές Android: οι προγραμματιστές υλοποιούν το onRestart, αλλά ξεχνούν να λάβουν υπόψη την επαναφορά μέσω onCreate μετά τη διακοπή της διεργασίας.

Παραδείγματα κώδικα με onStop σε Kotlin

Παράδειγμα 1: Βασική υλοποίηση onStop με ελευθέρωση αισθητήρων

Δείχνει σωστή διαγραφή από αισθητήρες και διακοπή κινούμενου σχεδίου κατά την απόκρυψη Activity. Μετά την επιστροφή στην οθόνη, οι πόροι αποκαθίστανται στο onStart.

kotlin
class MainActivity : AppCompatActivity() {
    private lateinit var sensorManager: SensorManager
    private var accelerometer: Sensor? = null
    private var rotationAnimator: ObjectAnimator? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    }

    override fun onStart() {
        super.onStart()
        accelerometer?.let {
            sensorManager.registerListener(sensorListener, it, SensorManager.SENSOR_DELAY_NORMAL)
        }
        rotationAnimator = ObjectAnimator.ofFloat(findViewById(R.id.icon), "rotation", 0f, 360f)
        rotationAnimator?.apply {
            duration = 3000
            repeatMode = ValueAnimator.RESTART
            repeatCount = ValueAnimator.INFINITE
            start()
        }
    }

    override fun onStop() {
        super.onStop()
        sensorManager.unregisterListener(sensorListener)
        rotationAnimator?.cancel()
    }

    override fun onRestart() {
        super.onRestart()
        Log.d("MainActivity", "Το Activity επιστρέφει από την κατάσταση Stopped")
    }

    private val sensorListener = SensorEventListener { event, _ ->
        Log.d("MainActivity", "Accel: x=${event.values[0]}, y=${event.values[1]}, z=${event.values[2]}")
    }
}

Ο κώδικας καταγράφει τον αισθητήρα επιταχυνσιόμετρου και ξεκινά ένα ατελείωτο κινούμενο σχέδιο περιστροφής στο onStart. Στο onStop, ο αισθητήρας απενεργοποιείται και το κινούμενο σχέδιο ακυρώνεται — αυτό αποτρέπει την κατανάλωση μπαταρίας όταν το Activity είναι κρυφό. Μετά την επιστροφή μέσω onRestart → onStart, οι πόροι αναδημιουργούνται.

Παράδειγμα 2: onStop με αποθήκευση κατάστασης μέσω SavedStateHandle

Σύγχρονη προσέγγιση με χρήση ViewModel + SavedStateHandle. Τα δεδομένα φόρμας αποθηκεύονται αυτόματα στο onStop χωρίς χειροκίνητο Bundle.

kotlin
class FormViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    var email: String
        get() = savedStateHandle["email"] ?: ""
        set(value) { savedStateHandle["email"] = value }

    var message: String
        get() = savedStateHandle["message"] ?: ""
        set(value) { savedStateHandle["message"] = value }
}

class FormActivity : AppCompatActivity() {
    private val viewModel: FormViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_form)
        Log.d("FormActivity", "onCreate: email=${viewModel.email}")
    }

    override fun onStop() {
        super.onStop()
        Log.d("FormActivity", "onStop: δεδομένα αποθηκεύτηκαν στο SavedStateHandle")
    }
}

Το SavedStateHandle αποθηκεύει αυτόματα τιμές στο Bundle κατά το onSaveInstanceState, το οποίο καλείται πριν από το onStop. Κατά την περιστροφή οθόνης ή διακοπή διεργασίας, τα δεδομένα αποκαθίστανται χωρίς απώλεια. Η Google συνιστά το SavedStateHandle για φόρμες και πρόχειρα αντί για άμεσο onSaveInstanceState.

Παράδειγμα 3: lifecycleScope για λειτουργίες στο onStop

Χρήση lifecycleScope με coroutines για ασύγχρονη αποθήκευση δεδομένων κατά τη μετάβαση στο onStop. Η coroutine ξεκινά στον dispatcher IO, χωρίς να μπλοκάρει το κύριο νήμα.

kotlin
class NoteActivity : AppCompatActivity() {
    private val noteRepository = NoteRepository()

    override fun onStop() {
        lifecycleScope.launch(Dispatchers.IO) {
            val text = findViewById<EditText>(R.id.note_content).text.toString()
            noteRepository.saveDraft(text)
            withContext(Dispatchers.Main) {
                Log.d("NoteActivity", "Πρόχειρο αποθηκεύτηκε στο onStop")
            }
        }
        super.onStop()
    }
}

Η coroutine lifecycleScope.launch ακυρώνεται αυτόματα εάν ο κύκλος ζωής Activity τελειώσει. Η χρήση Dispatchers.IO εγγυάται ότι η εγγραφή στη βάση ή στο αρχείο δεν μπλοκάρει την επιστροφή στο Activity. Σύμφωνα με την Google, τα coroutines στο lifecycleScope είναι η προτιμώμενη μέθοδος για ασύγχρονες λειτουργίες στο onStop.

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

Ποια είναι η διαφορά μεταξύ onStop και onDestroy;

onStop — το Activity παύει να είναι ορατό, αλλά παραμένει στη μνήμη σε κατάσταση Stopped. Το σύστημα μπορεί να επιστρέψει το Activity μέσω onRestart. onDestroy — το Activity καταστρέφεται, η μνήμη ελευθερώνεται. Μετά το onDestroy, η επιστροφή είναι δυνατή μόνο μέσω δημιουργίας νέας παρουσίας Activity (onCreate).

Είναι υποχρεωτική η κλήση super.onStop();

Ναι, υποχρεωτική. Η super.onStop() εξασφαλίζει τη σωστή λειτουργία των στοιχείων συστήματος: fragments, LoaderManager, ViewModelStore. Η παράλειψη της super.onStop() μπορεί να προκαλέσει διαρροές μνήμης και εσφαλμένη επαναφορά fragments. Πάντα καλείτε super.onStop() τελευταία ή πρώτα — η σειρά δεν είναι κρίσιμη, αλλά η κλήση είναι υποχρεωτική.

Πώς να ελέγξω αν κλήθηκε το onStop;

Χρησιμοποιήστε Log.d ή Timber σε κάθε μέθοδο κύκλου ζωής. Ενεργοποιήστε το φίλτρο logcat σύμφωνα με την ετικέτα του Activity σας. Για παραγωγή, χρησιμοποιήστε Android Vitals — η Google συλλέγει αυτόματα μετρήσεις κύκλου ζωής και εμφανίζει ανωμαλίες στο Play Console. Επίσης, διατίθεται παρακολούθηση κύκλου ζωής μέσω ProcessLifecycleOwner.

Τι συμβαίνει αν γίνει ρίψη εξαίρεσης στο onStop;

Μη καταγεγραμμένη εξαίρεση στο onStop προκαλεί Force Close της εφαρμογής. Το σύστημα δεν πιάνει εξαιρέσεις στα callbacks κύκλου ζωής. Εάν στο onStop εκτελούνται λειτουργίες που μπορεί να ρίξουν εξαίρεση (εργασία με αρχεία, δίκτυο), τυλίξτε τις σε try-catch και καταγράψτε το σφάλμα χωρίς να διακόψετε την εκτέλεση της super.onStop().

Πρέπει να ελευθερώσω Bitmap στο onStop;

Όχι, το Bitmap στο Activity θα συλλεχθεί από τον GC εάν δεν υπάρχουν αναφορές σε αυτό. Η αναγκαστική ελευθέρωση (recycle()) στο onStop δεν απαιτείται και είναι ακόμη επιβλαβής — εάν το Activity επιστρέψει μέσω onRestart, το Bitmap θα πρέπει να φορτωθεί ξανά. Χρησιμοποιήστε Glide ή Coil για φόρτωση εικόνων — αυτές οι βιβλιοθήκες διαχειρίζονται αυτόματα την προσωρινή μνήμη και τον κύκλο ζωής.

Σύνοψη

  • onStop — μέθοδος κύκλου ζωής Activity, που καλείται όταν η ορατότητα χαθεί εντελώς. Το Activity παραμένει στη μνήμη σε κατάσταση Stopped.
  • Μετά το onStop, δύο σενάρια είναι πιθανά: onRestart (επιστροφή στην οθόνη) ή onDestroy (καταστροφή Activity).
  • Στο onStop, ελευθερώστε αισθητήρες, κινούμενα σχέδια, κάμερα, location-listener — ό,τι δεν χρειάζεται όταν το Activity είναι αόρατο.
  • Το onStop διαφέρει από το onPause ως προς τον βαθμό ορατότητας: onPause — μερική, onStop — πλήρης απώλεια ορατότητας.
  • Το onSaveInstanceState καλείται πριν από το onStop — χρησιμοποιήστε το για αποθήκευση προσωρινής κατάστασης UI.
  • Τα coroutines lifecycleScope με Dispatchers.IO — η προτιμώμενη μέθοδος για ασύγχρονες λειτουργίες στο onStop.
  • Πάντα καλείτε super.onStop() και τυλίγετε επικίνδυνες λειτουργίες σε try-catch για να αποφύγετε το Force Close.

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

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

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

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