onResume — είναι μια μέθοδος του κύκλου ζωής Android που καλείται όταν το Activity ή το Fragment βγαίνει στο προσκήνιο και λαμβάνει εστίαση εισόδου. Σε αυτήν την κατάσταση η οθόνη είναι έτοιμη για αλληλεπίδραση με τον χρήστη: όλα τα γεγονότα αφής, πατήματα πλήκτρων και χειρονομίες κατευθύνονται σε αυτό το στοιχείο. Το onResume είναι η κατάσταση λειτουργίας του Activity στην οποία η εφαρμογή περνά το μεγαλύτερο μέρος του χρόνου της. Εδώ ακριβώς ανοίγουν την κάμερα, ξεκινούν την αναπαραγωγή βίντεο, αρχίζουν την αναγνώριση ομιλίας και καταγράφουν αισθητήρες ακρόασης που απαιτούν αποκλειστική πρόσβαση. Διαβάστε περισσότερα για τον πλήρη κύκλο ζωής Activity στο άρθρο Activity Lifecycle.
Κύρια σημεία
Το onResume — η τρίτη μέθοδος του κύκλου ζωής Activity, που καλείται μετά το onStart, σηματοδοτώντας την ετοιμότητα της οθόνης για πλήρη αλληλεπίδραση με τον χρήστη. Αυτή τη στιγμή το Activity βρίσκεται στην κορυφή της στοίβας εργασιών (back stack), το σύστημα κατευθύνει όλα τα γεγονότα εισόδου σε αυτό και η εφαρμογή μπορεί να ξεκινήσει οποιεσδήποτε λειτουργίες απαιτούν ενεργή συμμετοχή του χρήστη: βιντεοκλήσεις, παιχνίδια, εγγραφή ήχου, σχέδιο στο Canvas.
Το onResume ανήκει στη διάρκεια ζωής στο προσκήνιο (foreground lifetime) — το διάστημα μεταξύ onResume και onPause. Αυτή είναι η πιο ενεργή περίοδος λειτουργίας του Activity, όταν η εφαρμογή καταναλώνει μέγιστους πόρους: τον επεξεργαστή για την επεξεργασία αφών, την GPU για την απόδοση κινούμενων εικόνων, την κάμερα και το μικρόφωνο για καταγραφή βίντεο. Η κατανόηση αυτού του επιπέδου του κύκλου ζωής είναι κρίσιμη για τη βελτιστοποίηση της κατανάλωσης ενέργειας — οι πόροι που ανοίγονται στο onResume πρέπει να κλείνουν αμέσως στο onPause.
Σύμφωνα με τα δεδομένα του Google I/O 2025, ο μέσος χρόνος που ένα Activity περνά στην κατάσταση onResume ανά συνεδρία είναι 2–5 λεπτά για εφαρμογές ειδήσεων και 15–30 λεπτά για παιχνίδια και εφαρμογές ανταλλαγής μηνυμάτων. Τον υπόλοιπο χρόνο το Activity βρίσκεται σε καταστάσεις onPause, onStop ή onDestroy. Αυτό σημαίνει ότι η βελτιστοποίηση ακριβώς του κώδικα onResume δίνει το μεγαλύτερο κέρδος σε απόδοση και διάρκεια μπαταρίας.
Στο Activity η μέθοδος onResume καλείται κάθε φορά που η οθόνη λαμβάνει εστίαση εισόδου — κατά την πρώτη εκκίνηση, κατά την επιστροφή από άλλο Activity, κατά το κλείσιμο παραθύρου διαλόγου, κατά το ξεκλείδωμα της συσκευής. Είναι μια θερμή μέθοδος που μπορεί να κληθεί πολλές φορές κατά τη διάρκεια μιας συνεδρίας και η υλοποίησή της πρέπει να είναι όσο το δυνατόν πιο ελαφριά.
class CameraActivity : AppCompatActivity() {
private var cameraProvider: ProcessCameraProvider? = null
private var preview: Preview? = null
override fun onResume() {
super.onResume()
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
cameraProvider = cameraProviderFuture.get()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
preview = Preview.Builder().build().also {
it.setSurfaceProvider(binding?.viewFinder?.surfaceProvider)
}
try {
cameraProvider?.unbindAll()
cameraProvider?.bindToLifecycle(
this, cameraSelector, preview
)
} catch (e: Exception) {
Log.e("Camera", "Αποτυχία σύνδεσης κάμερας", e)
}
}, ContextCompact.getMainExecutor(this))
}
override fun onPause() {
super.onPause()
cameraProvider?.unbindAll()
preview = null
}
}
Το παράδειγμα με το CameraX δείχνει την κλασική χρήση του onResume/onPause: η κάμερα είναι ένας αποκλειστικός πόρος που μπορεί να χρησιμοποιηθεί μόνο από μία εφαρμογή κάθε φορά. Η σύνδεση της κάμερας με τον κύκλο ζωής μέσω bindToLifecycle κλείνει αυτόματα την κάμερα στο onPause, αλλά η ρητή κλήση unbindAll εγγυάται την άμεση απελευθέρωση. Αυτό είναι ιδιαίτερα σημαντικό κατά την εναλλαγή μεταξύ Activity: η κάμερα πρέπει να απελευθερωθεί πριν ένα άλλο Activity επιχειρήσει να την ανοίξει.
Το onResume στο Fragment καλείται αφού το Activity που το περιέχει λάβει το onResume. Ωστόσο, λόγω των ιδιαιτεροτήτων του FragmentManager και του ViewPager, η στιγμή κλήσης του onResume για το Fragment μπορεί να καθυστερήσει σε σχέση με το Activity. Για παράδειγμα, ένα Fragment στο ViewPager με offscreenPageLimit = 1 λαμβάνει onResume μόνο όταν γίνει η τρέχουσα σελίδα, όχι κατά την εκκίνηση του Activity.
class VideoPlayerFragment : Fragment() {
private var exoPlayer: ExoPlayer? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
exoPlayer = ExoPlayer.Builder(requireContext()).build()
binding?.playerView?.player = exoPlayer
}
override fun onResume() {
super.onResume()
exoPlayer?.play()
if (userVisibleHint) {
startBiometricAuth()
}
}
override fun onPause() {
exoPlayer?.pause()
stopBiometricAuth()
super.onPause()
}
}
Ο έλεγχος userVisibleHint στο Fragment.onResume είναι σχετικός για το ViewPager: το Fragment μπορεί να λάβει onResume αλλά να είναι κρυμμένο από τη γειτονική σελίδα (για παράδειγμα, κατά τη διάρκεια μιας ομαλής μετάβασης). Σε τέτοιες περιπτώσεις, η εκκίνηση βίντεο ή βιομετρικών στο onResume χωρίς έλεγχο ορατότητας θα οδηγήσει σε απροσδόκητη συμπεριφορά. Από το Fragment 1.5.0, συνιστάται η χρήση του FragmentTransaction.setMaxLifecycle() για ακριβή έλεγχο του κύκλου ζωής των τμημάτων στο ViewPager2.
Οι προγραμματιστές συχνά μπερδεύουν το onStart και το onResume, τοποθετώντας κώδικα σε λανθασμένη μέθοδο. Κύριος κανόνας: onStart — για πόρους που λειτουργούν σε ορατότητα; onResume — για πόρους που απαιτούν εστίαση εισόδου. Ας εξετάσουμε συγκεκριμένα σενάρια και τη σωστή επιλογή μεθόδου.
| Λειτουργία | Μέθοδος | Αιτιολόγηση |
|---|---|---|
| Συνδρομή σε γεωτοποθεσία | onStart / onStop | GPS μπορεί να λειτουργεί με μερική ορατότητα |
| Άνοιγμα κάμερας | onResume / onPause | Κάμερα — αποκλειστικός πόρος |
| BroadcastReceiver | onStart / onStop | Συστημικά γεγονότα δεν απαιτούν εστίαση |
| Αναπαραγωγή βίντεο | onResume / onPause | Το βίντεο πρέπει να είναι ορατό στον χρήστη |
| Σάρωση Bluetooth | onStart / onStop | Η σάρωση μπορεί να συνεχιστεί στο παρασκήνιο |
| Συσκευή εγγραφής (MediaRecorder) | onResume / onPause | Η εγγραφή απαιτεί ενεργό UI |
| Αισθητήρες ακρόασης | onResume / onPause | Αισθητήρες για παιχνίδια και χειρονομίες |
| Ενημέρωση δεδομένων | onStart | Φρέσκα δεδομένα χρειάζονται κατά την εμφάνιση |
Πρακτικός κανόνας: αν η λειτουργία πρέπει να διακοπεί όταν εμφανίζεται ένα παράθυρο διαλόγου — χρησιμοποιήστε onResume/onPause. Αν η λειτουργία μπορεί να συνεχιστεί με μερική κάλυψη της οθόνης — χρησιμοποιήστε onStart/onStop. Για παράδειγμα, η συσκευή αναπαραγωγής βίντεο πρέπει να θέτει σε παύση το βίντεο όταν ανοίγει ένας διάλογος (onPause), ενώ η γεωτοποθεσία μπορεί να συνεχίσει να ενημερώνεται (παραμένει στο onStart).
Αποκλειστικοί πόροι είναι στοιχεία της συσκευής που μπορούν να χρησιμοποιηθούν μόνο από μία εφαρμογή σε μια δεδομένη στιγμή. Κάμερα, μικρόφωνο, έξοδος βίντεο (MediaProjection), προσαρμογέας NFC σε λειτουργία ανάγνωσης, συσκευές USB σε λειτουργία accessory — όλοι αυτοί οι πόροι πρέπει να ανοίγονται στο onResume και να απελευθερώνονται στο onPause.
Το MediaRecorder χρησιμοποιείται για εγγραφή ήχου και βίντεο. Η αίτηση αδειών και η προετοιμασία του MediaRecorder γίνονται στο onCreate, και η έναρξη εγγραφής στο onResume. Εάν ο χρήστης μεταβεί σε άλλη εφαρμογή, το onPause θέτει σε παύση την εγγραφή και το onResume την επαναλαμβάνει. Αυτή είναι η τυπική συμπεριφορά για συσκευές εγγραφής και εφαρμογές καταγραφής βίντεο.
private var mediaRecorder: MediaRecorder? = null
private var isRecording = false
override fun onResume() {
super.onResume()
if (isRecording) {
mediaRecorder?.resume()
}
}
override fun onPause() {
if (isRecording) {
mediaRecorder?.pause()
}
super.onPause()
}
Ο βιομετρικός έλεγχος ταυτότητας (BiometricPrompt) πρέπει να καλείται μόνο όταν το Activity βρίσκεται σε κατάσταση onResume. Εάν το καλέσετε στο onCreate ή στο onStart, ο βιομετρικός διάλογος μπορεί να εμφανιστεί πριν το Activity ολοκληρώσει την αρχικοποίηση, οδηγώντας σε λανθασμένη επεξεργασία του αποτελέσματος. Η κλήση στο onResume εγγυάται ότι το βιομετρικό παράθυρο θα εμφανιστεί στο σωστό πλαίσιο.
Ας εξετάσουμε τρία δοκιμασμένα μοτίβα εργασίας με το onResume που εφαρμόζονται σε εμπορικά έργα: επαναφορά χρονοδιακόπτη αδράνειας, ενημέρωση ορατών δεδομένων και ενσωμάτωση με Jetpack Navigation.
Σε εφαρμογές με εμπιστευτικά δεδομένα (τραπεζικές, ιατρικά αρχεία) το onResume χρησιμοποιείται για επαναφορά του χρονοδιακόπτη αυτόματης αποσύνδεσης. Εάν ο χρήστης αλληλεπιδρά ενεργά με την εφαρμογή, το onResume καλείται σε κάθε μετάβαση μεταξύ οθονών και ο χρονοδιακόπτης επαναφέρεται. Εάν ο χρήστης ελαχιστοποιήσει την εφαρμογή, το onPause σταματά τον χρονοδιακόπτη και το onResume κατά την επιστροφή είτε τον επαναφέρει είτε ζητά επαναπιστοποίηση.
Η λίστα που πρέπει να εμφανίζει ενημερωμένα δεδομένα σε κάθε επιστροφή στην οθόνη ενημερώνεται στο onResume. Για παράδειγμα, εάν ο χρήστης δημιούργησε μια νέα εγγραφή σε άλλο Activity και επέστρεψε, το onResume φορτώνει ξανά τη λίστα από την τοπική βάση δεδομένων ή από την προσωρινή μνήμη του ViewModel. Αυτό εξασφαλίζει συνέπεια δεδομένων χωρίς χειροκίνητη κλήση του notifyDataSetChanged.
override fun onResume() {
super.onResume()
// Το ActivityResultLauncher επέστρεψε αποτέλεσμα — ενημέρωση λίστας
viewModel.refreshList()
// Επαναφορά χρονοδιακόπτη αδράνειας
inactivityTimer.reset()
}
Στο Jetpack Navigation το onResume του τμήματος καλείται σε κάθε επιστροφή σε αυτό μέσω πλοήγησης προς τα πίσω. Αυτή η ιδιότητα χρησιμοποιείται για επαναφορά της κατάστασης UI: απόκρυψη πληκτρολογίου, εκκαθάριση πεδίων αναζήτησης, ενημέρωση τίτλου γραμμής εργαλείων. Το OnBackPressedCallback σε συνδυασμό με το onResume παρέχει πλήρη έλεγχο της πλοήγησης χωρίς διπλασιασμό κώδικα.
Συχνές Ερωτήσεις
onStart — η οθόνη είναι ορατή. onResume — η οθόνη είναι ενεργή και έτοιμη για αλληλεπίδραση. Φανταστείτε: βλέπετε τηλεόραση (onStart), αλλά παίρνετε το τηλεχειριστήριο στο χέρι (onResume). Η τηλεόραση είναι πάντα ορατή, αλλά η αλληλεπίδραση ξεκινά μόνο με το τηλεχειριστήριο. Αν κάποιος καλύψει την τηλεόραση με μια κουρτίνα — η οθόνη παύει να είναι ορατή (onStop). Αν σας πάρουν το τηλεχειριστήριο — η αλληλεπίδραση σταματά (onPause), αλλά η τηλεόραση είναι ακόμα ορατή.
Το onResume καλείται κάθε φορά που το Activity λαμβάνει εστίαση εισόδου. Ελάχιστος αριθμός — μία φορά (κατά την εκκίνηση). Ο μέγιστος εξαρτάται από τα σενάρια χρήσης: εναλλαγή μεταξύ οθονών, άνοιγμα διαλόγων, γρήγορο κλείδωμα και ξεκλείδωμα της συσκευής — κάθε τέτοιο σενάριο καλεί το onResume κατά την επιστροφή στην οθόνη.
Η κάμερα — αποκλειστικός πόρος διαθέσιμος μόνο για μία εφαρμογή κάθε φορά. Εάν ανοίξετε την κάμερα στο onCreate ή στο onStart, θα παραμείνει κλειδωμένη για άλλες εφαρμογές ακόμα και όταν η εφαρμογή σας είναι ανενεργή. Το onResume εγγυάται ότι η κάμερα είναι ανοιχτή μόνο όταν το Activity βρίσκεται στο προσκήνιο και το onPause την κλείνει αμέσως. Αυτό είναι το πρότυπο ανάπτυξης Android, καθιερωμένο στην τεκμηρίωση των CameraX και Camera2 API.
Ναι, το onResume μπορεί να μην συμβεί εάν το Activity καλυφθεί από άλλο Activity αμέσως μετά την εμφάνισή του. Για παράδειγμα, το Activity A εκκινεί το Activity B στη μέθοδο onCreate ή onStart. Σε αυτήν την περίπτωση το A λαμβάνει onStart → onPause → onStop, παρακάμπτοντας το onResume. Το σύστημα δεν καλεί το onResume επειδή το Activity A δεν έλαβε ποτέ εστίαση εισόδου.
Στο onResume δεν πρέπει να εκτελούνται μεγάλες σύγχρονες λειτουργίες: φόρτωση μεγάλων δεδομένων από το δίκτυο, σύνθετα ερωτήματα SQL, επεξεργασία εικόνων. Η μέθοδος onResume λειτουργεί στο νήμα UI και οποιοδήποτε μπλοκάρισμα μεγαλύτερο από 100–200 ms οδηγεί σε καθυστέρηση απόκρισης της διεπαφής. Όλες οι βαριές λειτουργίες πρέπει να είναι ασύγχρονες — μέσω coroutines, RxJava ή WorkManager. Επίσης δεν συνιστάται η κλήση finish() στο onResume χωρίς έλεγχο — αυτό μπορεί να οδηγήσει σε ατελείωτο βρόχο αναδημιουργίας.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης