onStart: ουσία, ορατότητα Activity στην οθόνη Android

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

onStart — είναι η μέθοδος κύκλου ζωής του Android που καλείται όταν το Activity ή το Fragment γίνονται ορατά στον χρήστη. Αυτή τη στιγμή η οθόνη εμφανίζεται στην οθόνη της συσκευής, αλλά δεν μπορεί ακόμα να αλληλεπιδράσει με τον χρήστη — η εστίαση εισόδου απουσιάζει μέχρι την κλήση του onResume. Η μέθοδος onStart είναι ιδανική για την καταχώρηση συστημικών ακροατών, σύνδεση σε υπηρεσίες γεωτοποθεσίας και εκκίνηση κινούμενων σχεδίων που πρέπει να λειτουργούν όσο το στοιχείο είναι ορατό στην οθόνη. Διαβάστε περισσότερα για τον πλήρη κύκλο ζωής του Activity στο άρθρο Activity Lifecycle.

Κύρια σημεία

  • onStart — καλείται όταν το Activity ή το Fragment γίνεται ορατό στην οθόνη; προηγείται του onResume
  • Καταχώρηση ακροατών — BroadcastReceiver, LocationListener, SensorListener καταχωρούνται στο onStart και διαγράφονται στο onStop
  • Κινούμενα σχέδια — εκκίνηση κινούμενων σχεδίων που πρέπει να λειτουργούν όσο η οθόνη είναι ορατή; παύση στο onStop
  • Bound-υπηρεσίες — σύνδεση σε υπηρεσίες πελάτη-εξυπηρετητή μέσω bindService στο onStart, αποσύνδεση στο onStop
  • onStart vs onResume — onStart = ορατότητα, onResume = εστίαση + αλληλεπίδραση; διαφορετικά επίπεδα δραστηριότητας οθόνης
  • Fragment.onStart — καλείται μετά το Activity.onStart, όταν το Fragment γίνεται ορατό στον περιέκτη
  • Ζεύγος onStart/onStop — οι πόροι που συνδέονται στο onStart πρέπει υποχρεωτικά να απελευθερώνονται στο onStop για την πρόληψη διαρροών

Ουσία της μεθόδου onStart στο Android

onStart — η δεύτερη μέθοδος του κύκλου ζωής Activity, που καλείται από το σύστημα μετά το onCreate (ή μετά το onRestart κατά την επιστροφή από κατάσταση διακοπής). Τη στιγμή της κλήσης onStart, το Activity ή το Fragment γίνονται ορατά στην οθόνη. Ο χρήστης βλέπει τη διεπαφή, αλλά η οθόνη δεν είναι ακόμα έτοιμη για αλληλεπίδραση — η εστίαση εισόδου θα εμφανιστεί μόνο μετά το onResume.

Η μέθοδος onStart ανήκει στην “ορατή διάρκεια ζωής” (visible lifetime) του Activity — στο διάστημα μεταξύ onStart και onStop. Κατά τη διάρκεια αυτής της περιόδου, το Activity μπορεί να καλύπτεται εν μέρει από άλλα παράθυρα (για παράδειγμα, από διαφανές Activity ή παράθυρο διαλόγου), αλλά η διεπαφή χρήστη του παραμένει ορατή. Αυτό διακρίνει την ορατή διάρκεια ζωής από τη “διάρκεια ζωής στο προσκήνιο” (onResume — onPause), όταν το Activity έχει πλήρη εστίαση εισόδου.

Η κατανόηση αυτής της τριεπίπεδης ιεραρχίας είναι κρίσιμης σημασίας για τη σωστή κατανομή του κώδικα. onCreate — εφάπαξ αρχικοποίηση, onStart — σύνδεση ορατών πόρων, onResume — αποκλειστική πρόσβαση σε αποκλειστικούς πόρους. Ο προγραμματιστής που μπερδεύει αυτά τα επίπεδα κινδυνεύει να δημιουργήσει διαρροές μνήμης ή λανθασμένη συμπεριφορά της εφαρμογής κατά την εναλλαγή μεταξύ οθονών.

onStart στο Activity

Στο Activity, η μέθοδος onStart καλείται κάθε φορά που η οθόνη εμφανίζεται στην οθόνη — τόσο κατά την πρώτη εκκίνηση (μετά το onCreate) όσο και κατά την επιστροφή από τη λειτουργία παρασκηνίου (μετά το onRestart). Σε αντίθεση με το onCreate, το onStart μπορεί να κληθεί πολλές φορές κατά τη διάρκεια ζωής μιας παρουσίας Activity, επομένως εδώ τοποθετείται κώδικας που πρέπει να εκτελείται κάθε φορά που εμφανίζεται η οθόνη.

kotlin
class DashboardActivity : AppCompatActivity() {
    private val connectivityReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val isConnected = ... // έλεγχος ConnectivityManager
            binding?.statusIndicator?.setColor(
                if (isConnected) Color.GREEN else Color.RED
            )
        }
    }

    override fun onStart() {
        super.onStart()
        registerReceiver(
            connectivityReceiver,
            IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
        )
        SensorManager.getInstance().registerStepCounter()
    }

    override fun onStop() {
        unregisterReceiver(connectivityReceiver)
        SensorManager.getInstance().unregisterStepCounter()
        super.onStop()
    }
}

Βασικός κανόνας: όλοι οι πόροι που συνδέονται στο onStart πρέπει να απελευθερώνονται στο onStop. Αυτό εγγυάται ότι όταν το Activity είναι κρυμμένο από την οθόνη, δεν καταναλώνει μπαταρία, δεν ακούει συστημικά συμβάντα και δεν καταλαμβάνει μνήμη. Το Android Studio περιέχει κανόνες lint που προειδοποιούν για καταχώρηση BroadcastReceiver χωρίς αντίστοιχη διαγραφή.

onStart στο Fragment

Το onStart στο Fragment είναι στενά συνδεδεμένο με τον κύκλο ζωής του Activity-περιέκτη. Το Fragment λαμβάνει την κλήση onStart αφού το Activity στο οποίο βρίσκεται έλαβε onStart. Ωστόσο, εάν το Fragment προστέθηκε σε καθυστερημένη λειτουργία (FragmentTransaction.commit() χωρίς addToBackStack), το onStart μπορεί να κληθεί με καθυστέρηση.

kotlin
class MapFragment : Fragment() {
    private var mapView: MapView? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        mapView = MapView(requireContext())
        return mapView!!
    }

    override fun onStart() {
        super.onStart()
        mapView?.onStart()
        LocationService.connect(requireContext())
    }

    override fun onStop() {
        mapView?.onStop()
        LocationService.disconnect()
        super.onStop()
    }
}

Ιδιαιτερότητα του Fragment.onStart: εάν το Fragment βρίσκεται σε ViewPager με offscreenPageLimit = 1, τα γειτονικά θραύσματα θα λάβουν επίσης onStart προτού γίνουν ορατά. Αυτό μπορεί να οδηγήσει σε πρόωρη καταχώρηση ακροατών. Για τέτοιες περιπτώσεις, χρησιμοποιήστε τη μέθοδο setUserVisibleHint() ή τον έλεγχο isVisible μέσα στο onStart για να καταχωρείτε ακροατές μόνο για πραγματικά ορατά θραύσματα.

Διαφορά μεταξύ onStart και onResume

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

Ο πίνακας διαφορών δείχνει ξεκάθαρα σε ποια σενάρια καλείται κάθε μέθοδος:

ΣενάριοonStartonResume
Εκκίνηση εφαρμογήςΚαλείταιΚαλείται
Πάνω από το Activity ανοίγει DialogΔεν καλείταιonPause (απώλεια εστίασης)
Πάτημα κουμπιού «Αρχική»onStop (κρυφό)onPause → onStop
Επιστροφή από «Πρόσφατα»onStart (ορατό)onResume (εστίαση)
Περιστροφή οθόνηςonCreate → onStart→ onResume
Εισερχόμενη κλήσηonStop (κρυφό)onPause → onStop

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

Καταχώρηση ακροατών και υπηρεσιών

onStart — το βέλτιστο μέρος για καταχώρηση ακροατών που πρέπει να λειτουργούν μόνο όσο το Activity είναι ορατό στην οθόνη. Αυτό αφορά τρεις κύριους τύπους συστημικών στοιχείων: BroadcastReceiver για συστημικά συμβάντα, LocationListener για γεωτοποθεσία και SensorListener για αισθητήρες συσκευής.

BroadcastReceiver στο onStart

Το BroadcastReceiver καταχωρείται δυναμικά μέσω Context.registerReceiver() στο onStart και διαγράφεται στο onStop μέσω unregisterReceiver(). Η δυναμική καταχώρηση είναι προτιμότερη από τη στατική (στο manifest), καθώς περιορίζει τη διάρκεια ζωής του δέκτη στην περίοδο ορατότητας του Activity — η εφαρμογή δεν ξυπνά από συστημικά broadcast μηνύματα όταν το Activity είναι κρυφό.

kotlin
private val batteryReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent) {
        val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
        binding?.batteryText?.text = "$level%"
    }
}

override fun onStart() {
    super.onStart()
    registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
}

override fun onStop() {
    unregisterReceiver(batteryReceiver)
    super.onStop()
}

LocationListener και SensorListener

Γεωτοποθεσία και αισθητήρες — λειτουργίες που καταναλώνουν πόρους. Η αίτηση ενημερώσεων GPS στο onStart και η ακύρωση στο onStop εγγυάται ότι η εφαρμογή δεν καταναλώνει μπαταρία όταν η οθόνη είναι κρυφή. Για ακριβή ρύθμιση, χρησιμοποιείται requestLocationUpdates με ελάχιστο διάστημα και απόσταση — για παράδειγμα, 10 δευτερόλεπτα και 10 μέτρα, που παρέχει βέλτιστη ισορροπία μεταξύ ακρίβειας και κατανάλωσης ενέργειας.

Κινούμενα σχέδια και onStart

Η εκκίνηση κινούμενων σχεδίων στο onStart, όχι στο onCreate, εγγυάται ότι το κινούμενο σχέδιο ξεκινά κάθε φορά που εμφανίζεται η οθόνη. Εάν ξεκινήσετε το κινούμενο σχέδιο στο onCreate, θα λειτουργήσει μόνο κατά την πρώτη δημιουργία του Activity, αλλά όχι κατά την επιστροφή από τη λειτουργία παρασκηνίου. Το onStart καλείται κάθε φορά που το Activity γίνεται ορατό, καθιστώντας το ιδανικό μέρος για εκκίνηση κυκλικών κινούμενων σχεδίων και μεταβάσεων.

kotlin
private lateinit var pulseAnimator: ValueAnimator

override fun onStart() {
    super.onStart()
    pulseAnimator.start()
    binding?.loadingIndicator?.animate()?.alpha(1f)?.start()
}

override fun onStop() {
    pulseAnimator.cancel()
    binding?.loadingIndicator?.animate()?.cancel()
    super.onStop()
}

Για κινούμενα σχέδια που χρησιμοποιούν ObjectAnimator ή ValueAnimator, είναι σημαντικό να καλείτε cancel() στο onStop. Εάν το κινούμενο σχέδιο συνεχίζει να λειτουργεί μετά την απόκρυψη του Activity, καταναλώνει άσκοπα πόρους GPU και CPU, μειώνοντας την απόδοση της συσκευής και επιταχύνοντας την αποφόρτιση της μπαταρίας. Το Android Studio Profiler (γραφική παράσταση GPU) επιτρέπει την παρακολούθηση ενεργών κινούμενων σχεδίων και τον εντοπισμό διαρροών.

Ο κανόνας ζεύγους onStart/onStop ισχύει και για την εργασία με κάμερα προεπισκόπησης (CameraX). Το άνοιγμα της κάμερας στο onStart και το κλείσιμο στο onStop εγγυάται ότι η κάμερα δεν είναι αποκλεισμένη για άλλες εφαρμογές όταν η εφαρμογή σας δεν είναι ορατή στην οθόνη. Η παραβίαση αυτού του κανόνα είναι μία από τις συχνές αιτίες αρνητικών κριτικών στο Google Play.

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

Ποια είναι η διαφορά μεταξύ onStart και onResume για καταχώρηση ακροατών;

onStart — για ακροατές που πρέπει να λειτουργούν όσο η οθόνη είναι ορατή (BroadcastReceiver, LocationListener, SensorListener). onResume — για πόρους που απαιτούν αποκλειστική πρόσβαση (κάμερα, καταγραφή βίντεο, αναγνώριση ομιλίας). Οι ακροατές συστημικών συμβάντων δεν απαιτούν αποκλειστική πρόσβαση και μπορούν να λειτουργούν με μερική κάλυψη — καταχωρούνται στο onStart. Η κάμερα πρέπει να είναι ενεργή μόνο με πλήρη εστίαση — ανοίγει στο onResume.

Γιατί μπορεί να μην κληθεί το onStart;

Το onStart καλείται πάντα εάν το Activity μεταβαίνει σε ορατή κατάσταση. Το μόνο σενάριο χωρίς onStart — το Activity δημιουργείται και τερματίζεται αμέσως (για παράδειγμα, λόγω σφάλματος στο onCreate). Σε αυτή την περίπτωση, μετά το onCreate ακολουθεί αμέσως onDestroy. Αλλά αυτό είναι ένα σενάριο έκτακτης ανάγκης που δεν θα πρέπει να υπάρχει σε σωστά γραμμένο κώδικα.

Μπορεί το onStart να κληθεί χωρίς onResume;

Ναι, το onStart μπορεί να μην λάβει onResume εάν πάνω από το Activity ανοίξει αμέσως άλλο Activity ή διαφανές παράθυρο. Για παράδειγμα, εάν μετά το onCreate ξεκινήσει μια οθόνη αυθεντικοποίησης (Activity A → Activity B), στο Activity A το onStart καλείται, αλλά το onResume όχι — λαμβάνει αμέσως onPause → onStop όταν καλύπτεται από την οθόνη B.

Πόσες φορές μπορεί να κληθεί το onStart;

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

Αξίζει να φορτώνετε δεδομένα στο onStart;

Η φόρτωση δεδομένων στο onStart δικαιολογείται εάν τα δεδομένα πρέπει να ενημερώνονται κάθε φορά που εμφανίζεται η οθόνη. Για παράδειγμα, ροή ειδήσεων ή λίστα ειδοποιήσεων. Αλλά η φόρτωση πρέπει να είναι ασύγχρονη — μέσω coroutines με lifecycleScope, για να μην μπλοκάρει το νήμα UI. Για δεδομένα που δεν αλλάζουν μεταξύ εμφανίσεων οθόνης, αρκεί να φορτωθούν μία φορά στο onCreate.

Σύνοψη

  • onStart — μέθοδος ορατής διάρκειας ζωής; καλείται όταν το Activity ή το Fragment εμφανίζονται στην οθόνη
  • Καταχώρηση στο onStart — BroadcastReceiver, LocationListener, SensorListener καταχωρούνται στο onStart και διαγράφονται στο onStop
  • onStart vs onResume — onStart = ορατότητα, onResume = εστίαση εισόδου; διαφορετικά επίπεδα για διαφορετικούς τύπους πόρων
  • Κινούμενα σχέδια — εκκίνηση κυκλικών κινούμενων σχεδίων στο onStart, διακοπή στο onStop; αποτρέπει διαρροή πόρων GPU
  • Fragment.onStart — συνδεδεμένο με Activity.onStart; στο ViewPager καλείται για γειτονικά θραύσματα εκ των προτέρων
  • Κανόνας ζευγών — όλοι οι πόροι onStart πρέπει να απελευθερώνονται στο onStop, διαφορετικά διαρροή μνήμης και μπαταρίας
  • Φόρτωση δεδομένων — στο onStart φορτώνονται δεδομένα που πρέπει να ενημερώνονται σε κάθε εμφάνιση οθόνης

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

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

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

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