Κύρια Σημεία
App Lifecycle — μια πεπερασμένη μηχή καταστάσεων που περιγράφει όλες τις πιθανές καταστάσεις μιας εφαρμογής και τις μεταβάσεις μεταξύ τους. Κάθε κατάσταση καθορίζει αν η εφαρμογή μπορεί να εκτελέσει κώδικα, να εμφανίσει UI και να καταναλώσει πόρους. Το iOS και το Android έχουν παρόμοιο αλλά όχι ταυτόσημο μοντέλο — οι διαφορές οφείλονται στην αρχιτεκτονική του λειτουργικού: το iOS χρησιμοποιεί αυστηρό έλεγχο μνήμης (κατάσταση suspended), το Android — ευέλικτη διαχείριση διεργασιών μέσω onSaveInstanceState.
Στο iOS το lifecycle συνδέεται στενά με το foreground/background: η εφαρμογή είτε είναι ενεργή είτε ανασταλμένη. Στο Android το lifecycle είναι πιο κοκκώδες — η Activity/Window περνά από 6+ καταστάσεις, και η ίδια η διεργασία έχει επιπλέον lifecycle μέσω ProcessLifecycleOwner. Οι σύγχρονες εφαρμογές (από το 2024) χρησιμοποιούν όλο και περισσότερο αρχιτεκτονικά πρότυπα βασισμένα στο lifecycle: SwiftUI Lifecycle (iOS 16+) μέσω .scenePhase environment, Compose Lifecycle μέσω LifecycleEventObserver. Αυτά τα πρότυπα χειρίζονται αυτόματα την εναλλαγή περιβάλλοντος και αποτρέπουν διαρροές μνήμης. Σύμφωνα με την Google, η σωστή επεξεργασία lifecycle στο Android μειώνει την κατανάλωση μνήμης κατά 30–40% κατά τη διάρκεια εργασίας παρασκηνίου.
Στο iOS το lifecycle της εφαρμογής διαχειρίζεται μέσω της κλάσης UIApplicationDelegate (AppDelegate). Κύριες μέθοδοι: application(_:didFinishLaunchingWithOptions:) — αρχικοποίηση κατά την πρώτη εκκίνηση; applicationDidBecomeActive — εφαρμογή ορατή και έτοιμη για αλληλεπίδραση; applicationWillResignActive — μετάβαση σε ανενεργή κατάσταση (εισερχόμενη κλήση, κλείσιμο κουρτίνας); applicationDidEnterBackground — εφαρμογή κρυμμένη, υπάρχουν ~5 δευτερόλεπτα για αποθήκευση δεδομένων; applicationWillEnterForeground — επιστροφή από παρασκήνιο; applicationWillTerminate — τερματισμός (καλείται μόνο για παλαιές εφαρμογές χωρίς suspended).
Από το iOS 13, η Apple εισήγαγε το SceneDelegate (UISceneDelegate) για υποστήριξη εφαρμογών πολλαπλών παραθύρων σε iPad και macOS Catalyst. Το SceneDelegate διαχειρίζεται το lifecycle κάθε μεμονωμένης σκηνής (παραθύρου): scene(_:willConnectTo:options:) — δημιουργία σκηνής; sceneDidBecomeActive — σκηνή ενεργή; sceneWillResignActive — σκηνή χάνει εστίαση; sceneDidEnterBackground — σκηνή κρυμμένη. Το AppDelegate είναι υπεύθυνο για παγκόσμια συμβάντα (φόρτωση δεδομένων, push ειδοποιήσεις), και το SceneDelegate — για την κατάσταση UI κάθε παραθύρου. Στο SwiftUI το lifecycle διαχειρίζεται μέσω της τιμής περιβάλλοντος @Environment(\.scenePhase): .active, .inactive, .background — αυτό παρέχει ενοποιημένο API για εφαρμογές SwiftUI και UIKit.
Στο Android το lifecycle ξεκινά με την κλάση Application — ένα singleton που δημιουργείται πριν από οποιαδήποτε Activity. Η μέθοδος Application.onCreate() — πρώτο σημείο εισόδου, χρησιμοποιείται για καθολική αρχικοποίηση (Analytics, DI, Crash Reporting). Στη συνέχεια η Activity εκκινείται με τη σειρά: onCreate() → onStart() → onResume(). Κατά τη σύμπτυξη: onPause() → onStop() → onSaveInstanceState(). Κατά την καταστροφή: onDestroy(). Κατά την επιστροφή: onRestart() → onStart() → onResume().
ProcessLifecycleOwner (από AndroidX Lifecycle 2.2+) παρακολουθεί το lifecycle ολόκληρης της διεργασίας, όχι μεμονωμένης Activity. Παρέχει δύο καταστάσεις: ON_RESUME (εφαρμογή σε foreground) και ON_STOP (εφαρμογή κρυμμένη). Το ProcessLifecycleOwner λύνει το πρόβλημα "πότε πήγε η εφαρμογή στο παρασκήνιο" σε επίπεδο διεργασίας — αυτό είναι κρίσιμο για SDK, βιβλιοθήκες και αρθρωτές εφαρμογές. Στο Jetpack Compose το lifecycle διαχειρίζεται μέσω LifecycleEventObserver και collectAsStateWithLifecycle, το οποίο σταματά αυτόματα τη συλλογή δεδομένων σε λειτουργία παρασκηνίου. Το Android 14 (API 34) πρόσθεσε ειδοποίηση σχετικά με το foreground service lifecycle μέσω Service.onTimeout — η υπηρεσία πρέπει να ολοκληρωθεί εντός 6 ωρών, διαφορετικά το σύστημα τη διακόπτει υποχρεωτικά.
| iOS | Android | Περιγραφή |
|---|---|---|
| Not Running | — | Εφαρμογή δεν εκτελείται |
| didFinishLaunching | Application.onCreate | Πρώτη αρχικοποίηση κατά εκκίνηση |
| Active | onResume | Εφαρμογή ορατή και δέχεται είσοδο |
| Inactive | onPause | Προσωρινή απώλεια εστίασης (κλήση, κουρτίνα) |
| Background | onStop | Εφαρμογή κρυμμένη, κώδικας μπορεί να εκτελεστεί |
| Suspended | — | Κώδικας δεν εκτελείται, μνήμη δεσμευμένη |
| Will Terminate | onDestroy | Εφαρμογή τερματίζεται |
Κύρια διαφορά: το iOS μεταφέρει υποχρεωτικά την εφαρμογή σε Suspended (ο κώδικας δεν εκτελείται) 5-10 δευτερόλεπτα μετά την είσοδο στο παρασκήνιο. Το Android επιτρέπει εργασία παρασκηνίου (υπηρεσίες, WorkManager) για μεγαλύτερο χρονικό διάστημα, αλλά με περιορισμούς Doze Mode (Android 6+) και περιορισμούς παρασκηνίου (Android 12+). ProcessLifecycleOwner στο Android — ανάλογο του UIApplicationDidEnterBackgroundNotification στο iOS με τη διαφορά ότι ενεργοποιείται σε κάθε μετάβαση στο παρασκήνιο, όχι μόνο μετά από απώλεια εστίασης.
Βασική υλοποίηση AppDelegate με χειρισμό όλων των καταστάσεων κύκλου ζωής. Αποθήκευση δεδομένων κατά τη μετάβαση στο παρασκήνιο και ενημέρωση UI κατά την επιστροφή.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_: UIApplication, didFinishLaunchingWithOptions lo: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { Analytics.shared.initialize(); return true }
func applicationDidBecomeActive(_: UIApplication) { NotificationCenter.default.post(name: .appDidBecomeActive, object: nil) }
func applicationWillResignActive(_: UIApplication) { NotificationCenter.default.post(name: .appWillResignActive, object: nil) }
func applicationDidEnterBackground(_: UIApplication) { CoreDataManager.shared.saveContext(); UserDefaults.standard.synchronize() }
func applicationWillEnterForeground(_: UIApplication) { NetworkManager.shared.refreshSession() }
}AppDelegate — κεντρικό σημείο lifecycle. applicationDidEnterBackground — κρίσιμη μέθοδος: το iOS δίνει ~5 δευτερόλεπτα για αποθήκευση δεδομένων. applicationDidBecomeActive — ενημερώστε το UI, επανεκκινήστε κινούμενα σχέδια. Για SceneDelegate (iOS 13+) η λογική lifecycle διανέμεται σε σκηνές: sceneDidBecomeActive / sceneDidEnterBackground διαχειρίζονται μεμονωμένα παράθυρα.
SceneDelegate για εφαρμογές πολλαπλών παραθύρων iPad. Κάθε σκηνή έχει δικό της lifecycle, ανεξάρτητο από άλλα παράθυρα.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_: UIScene, willConnectTo s: UISceneSession, options o: UIScene.ConnectionOptions) {
guard let ws = (_ as? UIWindowScene) else { return }
window = UIWindow(windowScene: ws)
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
}
func sceneDidBecomeActive(_: UIScene) { PlayerManager.shared.resume() }
func sceneDidEnterBackground(_: UIScene) { PlayerManager.shared.pause(); CoreDataManager.shared.saveContext() }
func sceneDidDisconnect(_: UIScene) { PlayerManager.shared.cleanup() }
}SceneDelegate διαχειρίζεται το lifecycle μεμονωμένης σκηνής. sceneDidBecomeActive / sceneDidEnterBackground — αντίστοιχο των μεθόδων AppDelegate για συγκεκριμένο παράθυρο. sceneDidDisconnect καλείται όταν κλείνει η σκηνή (ο χρήστης έκλεισε το παράθυρο στο iPad). Για διατήρηση συμβατότητας με iOS 12 και παλαιότερα, το AppDelegate πρέπει να αντιγράφει τη λογική SceneDelegate. Στο iOS 17+ μπορείτε να χρησιμοποιήσετε @Observable για αυτόματη παύση/συνέχιση εργασιών βάσει scenePhase.
Το ProcessLifecycleOwner παρακολουθεί πότε η εφαρμογή βρίσκεται σε foreground/background σε επίπεδο διεργασίας. Αυτός είναι ο βέλτιστος τρόπος για καθολική διαχείριση lifecycle.
import android.app.Application
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
class MainApplication : Application() {
override fun onCreate() { super.onCreate(); ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleObserver()) }
}
class AppLifecycleObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START) fun onEnterForeground() { Analytics.shared.onForeground(); NetworkMonitor.shared.start() }
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onEnterBackground() { Analytics.shared.onBackground(); NetworkMonitor.shared.stop() }
}ProcessLifecycleOwner — ο μόνος σωστός τρόπος παρακολούθησης μετάβασης στο παρασκήνιο σε επίπεδο εφαρμογής. Το ON_START ενεργοποιείται όταν η εφαρμογή γίνεται ορατή (foreground), το ON_STOP — όταν είναι εντελώς κρυμμένη (background). Σε αντίθεση με το Activity lifecycle, το ProcessLifecycleOwner δεν συνδέεται με συγκεκριμένη οθόνη. Για Jetpack Compose χρησιμοποιήστε LifecycleResumeEffect ή collectAsStateWithLifecycle αντί για χειροκίνητη παρακολούθηση.
ViewModel + Lifecycle — η σωστή αρχιτεκτονική Android για εργασία με lifecycle. Το ViewModel καθαρίζεται αυτόματα στο onDestroy, αποτρέποντας διαρροές μνήμης.
import androidx.lifecycle.ViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
class TimerViewModel : ViewModel() {
private val _time = MutableLiveData<Long>()
val time: LiveData<Long> = _time
private var startTime = System.currentTimeMillis()
init { updateTime() }
private fun updateTime() { _time.value = System.currentTimeMillis() - startTime }
override fun onCleared() { super.onCleared(); Logger.d("ViewModel cleared — απελευθέρωση πόρων") }
}
// Στο Activity
class TimerActivity : AppCompatActivity() {
private val viewModel: TimerViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState); Logger.d("Activity created") }
override fun onResume() { super.onResume(); viewModel.time.observe(this) { Logger.d("Time: $it") } }
override fun onPause() { super.onPause(); Logger.d("Activity paused — παύση κινουμένων σχεδίων") }
override fun onDestroy() { super.onDestroy(); Logger.d("Activity destroyed — καθαρισμός") }
}ViewModel επιβιώνει από περιστροφή οθόνης και καταστρέφεται μόνο στο finish() Activity. onCleared() — μέρος για απελευθέρωση πόρων, διαγραφή από ροές. Το LiveData σταματά αυτόματα την παρακολούθηση στο onPause και συνεχίζει στο onResume — παρέχοντας προστασία από διαρροές και crashes κατά τη διάρκεια εργασίας παρασκηνίου. Στο Compose χρησιμοποιήστε collectAsStateWithLifecycle() για τον ίδιο σκοπό.
Συχνές Ερωτήσεις
Κατά τη σύμπτυξη, η εφαρμογή περνά από active σε inactive (σύντομα), στη συνέχεια σε background. Μετά από λίγα δευτερόλεπτα το σύστημα μπορεί να τη μεταφέρει σε suspended — ο κώδικας δεν εκτελείται, η μνήμη είναι δεσμευμένη. Σε περίπτωση έλλειψης μνήμης, η suspended εφαρμογή τερματίζεται (το willTerminate δεν καλείται). Αποθηκεύστε δεδομένα στο applicationDidEnterBackground — αυτό είναι το τελευταίο εγγυημένο σημείο αποθήκευσης.
Ελάχιστα υποχρεωτικές: applicationDidEnterBackground — αποθήκευση δεδομένων χρήστη; applicationWillEnterForeground — ενημέρωση UI; στο Android onPause — παύση κινουμένων σχεδίων/αισθητήρων. Το ProcessLifecycleOwner απλοποιεί το χειρισμό: onResume — onPause για foreground, onStart — onStop για ορατότητα. Τις υπόλοιπες καταστάσεις χειριστείτε ανάλογα με τις ανάγκες — δεν είναι όλες οι καταστάσεις κρίσιμες για κάθε εφαρμογή.
AppDelegate — καθολικός εκπρόσωπος ολόκληρης της εφαρμογής (εκκίνηση, μετάβαση σε παρασκήνιο). Το SceneDelegate (iOS 13+) διαχειρίζεται το lifecycle μεμονωμένου παραθύρου (σκηνής) — σε εφαρμογές πολλαπλών παραθύρων iPad κάθε σκηνή έχει δικό της lifecycle. Για iOS 12 και παλαιότερα, ολόκληρο το lifecycle χειρίζεται μέσω AppDelegate. Από iPadOS 16+ το SceneDelegate είναι υποχρεωτικό για το Stage Manager.
ProcessLifecycleOwner — στοιχείο από το AndroidX Lifecycle που παρακολουθεί το lifecycle ολόκληρης της εφαρμογής (διεργασίας), όχι μεμονωμένης Activity. Παρέχει δύο κύρια συμβάντα: ON_RESUME (εφαρμογή σε foreground) και ON_STOP (εφαρμογή σε background). Χρησιμοποιείται για αρχικοποίηση/καθαρισμό SDK, αναλυτικών στοιχείων, παρακολούθησης δικτύου — οτιδήποτε πρέπει να αντιδρά στη μετάβαση της εφαρμογής στο παρασκήνιο, ανεξάρτητα από την τρέχουσα οθόνη.
Στο Jetpack Compose χρησιμοποιήστε LifecycleEventObserver μέσω LocalLifecycleOwner.current.lifecycle ή τη συνάρτηση collectAsStateWithLifecycle(). Για οθόνες Compose εφαρμόστε LifecycleResumeEffect — ανάλογο του DisposableEffect που εκτελείται στο onResume και καθαρίζεται στο onPause. lifecycleScope.launchWhenResumed — coroutine που σταματά αυτόματα στο παρασκήνιο.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης