Active — az iOS-alkalmazás életciklusának aktív állapota, amelyben az alkalmazás az előtérben van, érintési eseményeket fogad és interakcióba lép a felhasználóval. Megvizsgáljuk, hogyan működik az Active állapot, mely UIApplicationDelegate delegált metódusok felelősek érte, és hogyan kell helyesen kezelni az Active és Inactive közötti átmeneteket Swiftben.
Főbb pontok
Active — a mobilalkalmazás életciklusának állapota, amelyben az alkalmazás az előtérben van, megjelenik a készülék képernyőjén, és aktívan interakcióba lép a felhasználóval. Ebben az állapotban az alkalmazás minden érintési eseményt, billentyűlenyomást, gyorsulásmérő- és giroszkóp-adatot fogad, valamint teljes hozzáféréssel rendelkezik a grafikus processzorhoz a felület megjelenítéséhez.
iOS-en az Active állapot az ötállapotú életciklus-modell része: Not Running → Inactive → Active → Inactive → Background → Suspended → Not Running. Androidon a megfelelője az Activity állapota az onResume meghívása után, amikor az Activity a verem tetején van és fogadja a felhasználói bemenetet. Az Active az egyetlen állapot, amelyben a UI teljesen interaktív és reagál a gesztusokra, görgetésre, kattintásokra és animációkra.
A rendszer a legmagasabb processzor- és RAM-prioritást biztosítja az Active állapotú alkalmazásnak. Ez azt jelenti, hogy a rendszer nem szünteti meg az ilyen alkalmazást erőforráshiány esetén — először a háttér- és felfüggesztett folyamatok kerülnek eltávolításra. Az alkalmazásnak azonban hatékonyan kell használnia az erőforrásokat, hogy ne merítse le az akkumulátort és ne okozzon CPU-throttlingot.
A felhasználó számára az Active az alkalmazással való munka normál állapota. A felhasználó látja a felületet, nyomogathatja a gombokat, kitöltheti az űrlapokat, görgetheti a hírfolyamot. Az állapot bármilyen megszakítása (hívás, értesítés, felfelé húzás a Control Centerhez) áthelyezi az alkalmazást Inactive-be, ami után visszatérhet Active-be vagy Background-be mehet.
Az iOS az UIApplicationMain-t használja az állapot kezelésére. Az Active-be való átmenetkor a rendszer meghívja az applicationDidBecomeActive-ot. A SwiftUI esetében a hasonló mechanizmus a scenePhase megfigyelése az Environment-en keresztül. Az Android az onResume-t használja az Activity előtérben lévő aktivitásának jelzőjeként. Mindkét megközelítés garantálja, hogy az alkalmazás értesítést kap az állapotváltozásról, és alkalmazkodni tud a viselkedéséhez.
| Platform | Metódus/esemény | Swift (UIKit) | SwiftUI | Android (Kotlin) |
|---|---|---|---|---|
| iOS | Átmenet Active-be | applicationDidBecomeActive | scenePhase == .active | — |
| iOS | Kilépés Active-ből | applicationWillResignActive | scenePhase == .inactive | — |
| Android | Átmenet Active-be | — | — | onResume() |
| Android | Kilépés Active-ből | — | — | onPause() |
iOS-ben az Active állapotot az UIApplicationDelegate kezeli. A fő metódus — applicationDidBecomeActive(_:). Ez az alkalmazás első indításakor és az Inactive-ből való visszatéréskor hívódik meg. Ez a metódus ideális hely az Inactive-be való átmenetkor felfüggesztett feladatok folytatására: animációk indítása, időzítők folytatása, érzékelők újraindítása, szerver adatfrissítések ellenőrzése.
Az iOS 13-tól az Apple bevezette az UISceneDelegate-t a több ablak támogatására iPad-en. Ebben az esetben az applicationDidBecomeActive helyébe a sceneDidBecomeActive lép minden jelenet esetében. Azok az alkalmazások, amelyek csak egy képernyőt támogatnak, továbbra is használhatják az UIApplicationDelegate-t. Mindkét megközelítés meghívásra kerül abban a pillanatban, amikor az alkalmazás vagy jelenet aktívvá válik.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// Az alkalmazás aktívvá vált — folytatjuk a feladatokat
func applicationDidBecomeActive(_ application: UIApplication) {
resumeAnimations()
restartTimers()
refreshDataIfNeeded()
startObservingSensors()
}
// Az alkalmazás elveszíti az aktivitást — felfüggesztjük
func applicationWillResignActive(_ application: UIApplication) {
pauseAnimations()
stopTimers()
saveDraftData()
}
private func resumeAnimations() {
UIView.animate(withDuration: 0.3) {
// UI-animációk folytatása
}
}
private func refreshDataIfNeeded() {
let lastRefresh = UserDefaults.standard.object(forKey: "lastRefresh") as? Date ?? .distantPast
if Date().timeIntervalSince(lastRefresh) > 300 {
fetchDataFromServer()
}
}
}A kód az Active helyes kezelését mutatja UIKit-ben. az applicationDidBecomeActive folytatja az animációkat, időzítőket, és ellenőrzi, hogy szükség van-e adatfrissítésre. Az applicationWillResignActive felfüggeszt mindent, ami erőforrásokat fogyaszthat, és elmenti a piszkozatokat. Az ilyen metóduspár garantálja, hogy az alkalmazás helyesen reagál az állapotváltozásra.
A SwiftUI-ban nincs AppDelegate — az állapotkezelés az Environment<ScenePhase> segítségével történik. Az .active érték akkor kerül beállításra, amikor a jelenet az előtérben van és interaktív. A SwiftUI automatikusan újraindítja az animációkat és frissítéseket az Active-be való visszatéréskor. A fejlesztőnek csak fel kell iratkoznia az onChange-re a mellékhatások végrehajtásához.
import SwiftUI
@main
struct ActiveDemoApp: App {
@Environment(\.scenePhase) private var scenePhase
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { oldPhase, newPhase in
switch newPhase {
case .active:
print("A jelenet aktívvá vált")
resumeWork()
case .inactive:
print("A jelenet inaktívvá vált")
pauseWork()
case .background:
print("A jelenet háttérbe került")
saveState()
@unknown default:
break
}
}
}
private func resumeWork() {
// Hálózati kérések, animációk folytatása
}
private func pauseWork() {
// Időérzékeny feladatok felfüggesztése
}
private func saveState() {
// Alkalmazás állapotának mentése
}
}A SwiftUI-ban a scenePhase az egyetlen igazságforrás az alkalmazás állapotáról. Az onChange lehetővé teszi műveletek végrehajtását minden átmenetkor. Fontos megjegyezni, hogy a scenePhase csak iOS 14+ és SwiftUI Lifecycle esetén érhető el. Az UIKit alkalmazásokhoz SwiftUI képernyőkkel használja az UIApplicationDelegate megközelítést.
Active több úton is elérhető. Az első és nyilvánvaló — hideg indítás: a felhasználó az ikonra kattint, az alkalmazás a Not Running-ból az Inactive-en keresztül az Active-be kerül. A második — visszatérés a háttérből: a felhasználó az App Switcher-en keresztül visszavált az alkalmazásba, az alkalmazás áthalad az Inactive-en és Active lesz. A harmadik — visszatérés ideiglenes megszakításból: a felhasználó befejez egy hívást, bezárja a Control Center-t vagy válaszol egy értesítésre — az alkalmazás visszatér az Inactive-ből az Active-be.
Not Running → Inactive → Active — hideg indítás. Background → Inactive → Active — visszatérés a háttérből. Inactive → Active — visszatérés ideiglenes megszakításból. Minden esetben az applicationDidBecomeActive meghívásra kerül, de a kontextus eltérő lehet. Hideg indításkor az Active előtt a didFinishLaunchingWithOptions hívódik meg, háttérből való visszatéréskor — a willEnterForeground. A fejlesztő ezeket a különbségeket felhasználhatja az állapot-visszaállítási stratégia kiválasztásához.
| Forgatókönyv | Átmenet útvonala | iOS callback-ek | Android callback-ek |
|---|---|---|---|
| Hideg indítás | Not Running → Active | didFinishLaunching → didBecomeActive | onCreate → onStart → onResume |
| Visszatérés a háttérből | Background → Active | willEnterForeground → didBecomeActive | onRestart → onStart → onResume |
| Visszatérés Suspended-ből | Suspended → Active | willEnterForeground → didBecomeActive | onRestart → onStart → onResume |
| Megszakítás után | Inactive → Active | didBecomeActive | onResume |
Fontos megjegyzés: a Suspended-ből való visszatéréskor az iOS nem hívja meg a didFinishLaunchingWithOptions-t, mivel az alkalmazás már be volt töltve a memóriába. Ez azt jelenti, hogy az ebben a metódusban elhelyezett inicializáló kód nem fut le újra. A fejlesztők gyakran elfelejtik ezt, és áthelyezik a kritikus logikát az applicationWillEnterForeground vagy applicationDidBecomeActive metódusba mindkét forgatókönyv esetére.
Androidban az Active megfelelője az Activity állapota az onResume() meghívása után. Az Activity akkor tekinthető aktívnak, ha az előtérben van és fogadja a felhasználói bemenetet. Ez az állapot az Activity-verem tetejének felel meg. Ha egy másik Activity jelenik meg felette (akár részlegesen is), az aktuális Activity az onPause állapotba kerül — az iOS Inactive megfelelője.
Az Android kulcsfontosságú különbsége — több Activity lehet egyszerre aktív multi-window módban (split screen, freeform). Ebben az esetben az az Activity, amellyel a felhasználó interakcióba lép, aktívnak tekintendő, a szomszédos pedig felfüggesztettnek (onPause). Az iOS nem támogatja a multi-window-t iPhone-on, csak iPad-en az UIScene segítségével.
class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
// Az alkalmazás aktívvá vált — folytatjuk a feladatokat
resumeCameraPreview()
startLocationUpdates()
activateSensors()
}
override fun onPause() {
super.onPause()
// Az alkalmazás elveszíti az aktivitást — erőforrásokat szabadítunk fel
releaseCamera()
stopLocationUpdates()
deactivateSensors()
}
private fun resumeCameraPreview() {
// Kamera előnézetének elindítása (engedély szükséges)
cameraProvider?.unbindAll()
cameraProvider?.bindToLifecycle(
this,
cameraSelector,
preview,
imageAnalyzer
)
}
private fun startLocationUpdates() {
val locationRequest = LocationRequest.Builder(
Priority.PRIORITY_HIGH_ACCURACY, 5000
).build()
locationClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
}A kód az Active kezelését mutatja Androidban az onResume/onPause segítségével. Az onResume folytatja a kamerával való munkát, a geolokációt és az érzékelőket — olyan erőforrásokat, amelyek csak akkor lehetnek aktívak, amikor az alkalmazás látható a felhasználó számára. Az onPause felszabadítja ezeket az erőforrásokat, hogy ne merítse az akkumulátort. A CameraX lifecycle-aware API automatikusan leállítja az előnézetet az onPause-kor.
Első szabály — ne végezzen nehéz műveleteket az applicationDidBecomeActive vagy onResume metódusban. Adatok betöltése, JSON elemzése, adatbázissal való munka — mindennek aszinkronnak kell lennie, és nem blokkolhatja a fő szálat. Használjon GCD-t (DispatchQueue) iOS-en és Coroutines-t Kotlinban a háttérfeladatokhoz. A fő szálnak csak a UI frissítése és aszinkron műveletek indítása a feladata.
Második szabály — szinkronizálja az állapotot minden Active-be való visszatéréskor. A felhasználó megváltoztathatta a beállításokat a rendszeralkalmazásban, kaphatott push értesítést vagy frissíthette az adatokat egy másik alkalmazásban. Ellenőrizze a gyorsítótár érvényességét az Active-be való átmenetkor — lehet, hogy az adatok elavultak a felhasználó távolléte alatt.
Harmadik szabály — ne hagyatkozzon az Active-re mint egyetlen állapotra. Az alkalmazás kihagyhatja az Active-t, és közvetlenül a Not Running-ból a Background-be kerülhet (ha háttérben van elindítva). iOS-en ez akkor történik, ha az alkalmazás push értesítésen keresztül indul el a content-available opcióval. Androidon — BroadcastReceiver-en keresztüli indításkor. Mindig ellenőrizze az aktuális állapotot a UI műveletek végrehajtása előtt.
Negyedik szabály — használja az Activity Result API-t Androidon az onActivityResult helyett. Ez lehetővé teszi a kamera, galéria vagy engedélyek hívásának eredményének közvetlen kezelését az Active állapotban, adatvesztés nélkül az Activity újralétrehozásakor. iOS-hez használja az async/await-t az UIApplication.shared.open segítségével a rendszerpárbeszédpanelekhez.
import UIKit
final class ActiveStateManager {
static let shared = ActiveStateManager()
private var isActive = false
func setActive(_ active: Bool) {
isActive = active
if active {
NotificationCenter.default.post(name: .appDidBecomeActive, object: nil)
}
}
func performWhenActive(_ block: @escaping () -> Void) {
if isActive {
block()
} else {
// A végrehajtás elhalasztása az Active-be való visszatérésig
NotificationCenter.default.addObserver(
forName: .appDidBecomeActive,
object: nil,
queue: .main
) { _ in
block()
}
}
}
}
extension Notification.Name {
static let appDidBecomeActive = Notification.Name("appDidBecomeActive")
}A kód egy Active állapotkezelőt mutat, amely lehetővé teszi az alkalmazás más komponensei számára az aktuális aktív állapot ellenőrzését. A performWhenActive vagy azonnal végrehajtja a blokkot (ha az alkalmazás aktív), vagy elhalasztja a végrehajtást az Active-be való visszatérésig. Ez hasznos azoknak a szolgáltatásoknak, amelyeknek a felhasználó alkalmazásba való visszatérése után kell végrehajtaniuk egy műveletet.
Gyakran Ismételt Kérdések
A metódus minden alkalommal meghívódik, amikor az alkalmazás aktív állapotba kerül: az első indításkor, a háttérből való visszatéréskor, a Control Center vagy Notification Center bezárása után, egy hívás befejezése után. Egy normál munkamenetben 5–10 alkalommal hívódhat meg, a felhasználó tevékenységétől függően. Ne helyezzen egyszeri inicializálást ebbe a metódusba.
Visible — egy nem hivatalos kifejezés, ami azt jelenti, hogy az alkalmazás látható a képernyőn, de lehet, hogy nem fogad eseményeket (például részben letakarja egy másik ablak iPad-en). Active — a hivatalos állapot, amelyben az alkalmazás látható és interaktív is. iPhone-on a Visible alkalmazás mindig Active, iPad-en lehetséges a Visible + Inactive helyzet.
willEnterForeground a háttérből való visszatéréskor hívódik meg, de az alkalmazás még nem aktív — Inactive állapotban van. didBecomeActive azután hívódik meg, hogy az alkalmazás teljesen interaktívvá vált. Ha egy műveletet a felhasználó által látott felület előtt kell végrehajtani — használja a willEnterForeground-ot. Ha a megjelenítés után — a didBecomeActive-ot.
Nem. Az Active feltételezi, hogy az alkalmazás az előtérben van és megjelenik a képernyőn. Látható UI nélkül az alkalmazás lehet Background vagy Suspended állapotban. Kivétel — iPad multi-window, ahol az egyik ablak aktív lehet, a másik nem, de mindkettő látható. A VoiceOver és a diktafon nem változtatja meg ezt a szabályt.
Az iOS szimulátoron nyomja meg a Cmd+Shift+H billentyűkombinációt a kezdőképernyőre való lépéshez (az alkalmazás Background-be kerül), majd kattintson újra az alkalmazás ikonjára. Használja a Cmd+L billentyűkombinációt a képernyő zárolásához (willResignActive) és feloldásához (didBecomeActive). Az Inactive teszteléséhez hívja elő a Control Center-t (Cmd+Shift+; macOS billentyűzethez) vagy a Notification Center-t.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is