App Lifecycle: چیست، حالت‌های برنامه در iOS و Android

نویسنده: IT Sectr منتشر شده: 2026-03-02 زمان مطالعه: 8 دقیقه
App Lifecycle (چرخه حیات برنامه) — توالی حالت‌هایی که یک برنامه موبایل از راه‌اندازی تا پایان طی می‌کند. درک lifecycle برای مدیریت منابع، ذخیره‌سازی داده‌ها و تضمین پایداری حیاتی است. در iOS برنامه از حالت‌های زیر عبور می‌کند: Not Running → Active → Inactive → Background → Suspended. در Android — از onCreate → onStart → onResume → onPause → onStop → onDestroy + onRestart. هر حالت به توسعه‌دهنده فرصتی برای ذخیره وضعیت، آزادسازی منابع یا آماده‌سازی برای بازگشت می‌دهد. طبق Apple Documentation، نادیده گرفتن رویدادهای lifecycle علت 40٪ کرش‌ها هنگام کوچک‌سازی برنامه است. در IT Sectr ما ProcessLifecycleOwner را در Android و الگوی AppDelegate را در iOS به عنوان استانداردهای اجباری برای همه پروژه‌ها پیاده‌سازی کردیم — این کار تعداد باگ‌های مربوط به پس‌زمینه را 60٪ کاهش داد.

نکات اصلی

  • App Lifecycle — مجموعه حالت‌های برنامه: از راه‌اندازی تا پایان، هر یک با اقدامات مشخص توسعه‌دهنده.
  • AppDelegate — کلاس مرکزی iOS برای پردازش lifecycle: didFinishLaunching، didEnterBackground، willEnterForeground.
  • SceneDelegate — نماینده صحنه جداگانه (iOS 13+)، مدیریت lifecycle هر پنجره در برنامه‌های چندپنجره‌ای.
  • ProcessLifecycleOwner — کامپوننت Android از AndroidX Lifecycle، ردیابی lifecycle کل فرآیند.
  • Application.onCreate — اولین نقطه ورود برنامه Android، قبل از هر Activity فراخوانی می‌شود.

App Lifecycle چیست؟

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: AppDelegate و SceneDelegate

در 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 مسئول رویدادهای جهانی (بارگذاری داده، اعلان‌های پوش) است و SceneDelegate — برای وضعیت UI هر پنجره. در SwiftUI lifecycle از طریق مقدار محیطی @Environment(\.scenePhase) مدیریت می‌شود: .active، .inactive، .background — این یک API یکپارچه برای برنامه‌های SwiftUI و UIKit فراهم می‌کند.

چرخه حیات Android: Application و ProcessLifecycleOwner

در Android lifecycle با کلاس Application شروع می‌شود — سینگلتونی که قبل از هر 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 ساعت تمام شود، در غیر این صورت سیستم آن را اجباری متوقف می‌کند.

مقایسه lifecycle iOS و Android

iOS Android توضیح
Not Running برنامه راه‌اندازی نشده
didFinishLaunching Application.onCreate مقداردهی اولیه در راه‌اندازی
Active onResume برنامه قابل مشاهده و دریافت ورودی
Inactive onPause از دست دادن موقت فوکوس (تماس، پرده)
Background onStop برنامه پنهان، کد می‌تواند اجرا شود
Suspended کد اجرا نمی‌شود، حافظه رزرو شده
Will Terminate onDestroy برنامه در حال پایان است

تفاوت اصلی: iOS برنامه را 5-10 ثانیه پس از رفتن به پس‌زمینه به زور به Suspended منتقل می‌کند (کد اجرا نمی‌شود). Android کار پس‌زمینه (سرویس‌ها، WorkManager) را برای مدت طولانی‌تری مجاز می‌داند، اما با محدودیت‌های Doze Mode (Android 6+) و محدودیت‌های پس‌زمینه (Android 12+). ProcessLifecycleOwner در Android — معادل UIApplicationDidEnterBackgroundNotification در iOS با این تفاوت که در هر انتقال به پس‌زمینه فعال می‌شود، نه فقط پس از از دست دادن فوکوس.

نمونه کدها

iOS: AppDelegate با متدهای lifecycle

پیاده‌سازی پایه AppDelegate با مدیریت تمام حالت‌های چرخه حیات. ذخیره داده‌ها هنگام انتقال به پس‌زمینه و به‌روزرسانی UI هنگام بازگشت.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        Analytics.shared.initialize()
        return true
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        NotificationCenter.default.post(name: .appDidBecomeActive, object: nil)
    }

    func applicationWillResignActive(_ application: UIApplication) {
        NotificationCenter.default.post(name: .appWillResignActive, object: nil)
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        CoreDataManager.shared.saveContext()
        UserDefaults.standard.synchronize()
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        NetworkManager.shared.refreshSession()
    }
}

AppDelegate — نقطه مرکزی lifecycle. applicationDidEnterBackground — متد حیاتی: iOS ~5 ثانیه برای ذخیره داده‌ها فرصت می‌دهد. applicationDidBecomeActive — UI را به‌روز کنید، انیمیشن‌ها را دوباره راه‌اندازی کنید. برای SceneDelegate (iOS 13+) منطق lifecycle بین صحنه‌ها تقسیم می‌شود: sceneDidBecomeActive / sceneDidEnterBackground پنجره‌های جداگانه را مدیریت می‌کنند.

iOS: SceneDelegate (iOS 13+)

SceneDelegate برای برنامه‌های چندپنجره‌ای iPad. هر صحنه lifecycle مستقل خود را دارد.

swift
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: windowScene)
        window?.rootViewController = ViewController()
        window?.makeKeyAndVisible()
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        PlayerManager.shared.resume()
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        PlayerManager.shared.pause()
        CoreDataManager.shared.saveContext()
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        PlayerManager.shared.cleanup()
    }
}

SceneDelegate lifecycle یک صحنه جداگانه را مدیریت می‌کند. sceneDidBecomeActive / sceneDidEnterBackground — معادل متدهای AppDelegate برای یک پنجره خاص. sceneDidDisconnect هنگام بستن صحنه فراخوانی می‌شود (کاربر پنجره را در iPad بست). برای حفظ سازگاری با iOS 12 و پایین‌تر، AppDelegate باید منطق SceneDelegate را تکرار کند. در iOS 17+ می‌توانید از @Observable برای توقف/ازسرگیری خودکار وظایف بر اساس scenePhase استفاده کنید.

Android: Application با ProcessLifecycleOwner

ProcessLifecycleOwner زمانی که برنامه در foreground/background است را در سطح فرآیند ردیابی می‌کند. این روش بهینه برای مدیریت سراسری lifecycle است.

kotlin
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 استفاده کنید.

Android: Activity Lifecycle با ViewModel

ViewModel + Lifecycle — معماری صحیح Android برای کار با lifecycle. ViewModel به طور خودکار در onDestroy پاک می‌شود و از نشت جلوگیری می‌کند.

kotlin
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 ازسر می‌گیرد — این محافظت در برابر نشت و کرش در حین کار پس‌زمینه را فراهم می‌کند. در Compose از collectAsStateWithLifecycle() برای همین هدف استفاده کنید.

سوالات متداول

وقتی کاربر برنامه iOS را کوچک می‌کند چه اتفاقی می‌افتد؟

هنگام کوچک‌سازی، برنامه از active به inactive (کوتاه مدت)، سپس به background می‌رود. پس از چند ثانیه سیستم ممکن است آن را به suspended منتقل کند — کد اجرا نمی‌شود، حافظه رزرو شده است. در صورت کمبود حافظه، برنامه suspended خاتمه می‌یابد (willTerminate فراخوانی نمی‌شود). داده‌ها را در applicationDidEnterBackground ذخیره کنید — این آخرین نقطه تضمین شده برای ذخیره است.

آیا باید همه حالت‌های App Lifecycle را پردازش کرد؟

حداقل اجباری: applicationDidEnterBackground — ذخیره داده‌های کاربر؛ applicationWillEnterForeground — به‌روزرسانی UI؛ در Android onPause — توقف انیمیشن‌ها/حسگرها. ProcessLifecycleOwner پردازش را ساده می‌کند: onResume — onPause برای foreground، onStart — onStop برای دید. سایر حالت‌ها را در صورت نیاز پردازش کنید — همه حالت‌ها برای هر برنامه‌ای حیاتی نیستند.

SceneDelegate چه تفاوتی با AppDelegate دارد؟

AppDelegate — نماینده جهانی کل برنامه (راه‌اندازی، انتقال به پس‌زمینه). SceneDelegate (iOS 13+) lifecycle یک پنجره جداگانه (صحنه) را مدیریت می‌کند — در برنامه‌های چندپنجره‌ای iPad هر صحنه lifecycle خود را دارد. برای iOS 12 و پایین‌تر، کل lifecycle از طریق AppDelegate پردازش می‌شود. از iPadOS 16+ SceneDelegate برای Stage Manager اجباری است.

ProcessLifecycleOwner در Android چیست؟

ProcessLifecycleOwner — کامپوننتی از AndroidX Lifecycle که lifecycle کل برنامه (فرآیند) را ردیابی می‌کند، نه یک Activity جداگانه. دو رویداد اصلی ارائه می‌دهد: ON_RESUME (برنامه در foreground) و ON_STOP (برنامه در background). برای مقداردهی اولیه/پاکسازی SDKها، تحلیل‌ها، مانیتورهای شبکه استفاده می‌شود — هر چیزی که باید به انتقال برنامه به پس‌زمینه واکنش نشان دهد، صرف‌نظر از صفحه فعلی.

چگونه lifecycle را در Jetpack Compose مدیریت کنیم؟

در Jetpack Compose از LifecycleEventObserver از طریق LocalLifecycleOwner.current.lifecycle یا تابع collectAsStateWithLifecycle() استفاده کنید. برای صفحات Compose از LifecycleResumeEffect استفاده کنید — معادل DisposableEffect که در onResume اجرا و در onPause پاک می‌شود. lifecycleScope.launchWhenResumed — کوروتینی که به طور خودکار در پس‌زمینه متوقف می‌شود.

خلاصه

  • App Lifecycle — ماشین حالت محدود برنامه که مدیریت منابع، ذخیره داده و پایداری را تعیین می‌کند.
  • iOS AppDelegate (applicationDidEnterBackground) — متد حیاتی برای ذخیره داده‌ها هنگام انتقال به پس‌زمینه در 5 ثانیه.
  • iOS SceneDelegate (iOS 13+) lifecycle هر صحنه را جداگانه مدیریت می‌کند — برای برنامه‌های چندپنجره‌ای iPad اجباری است.
  • Android ProcessLifecycleOwner — مشاهده‌گر سراسری lifecycle فرآیند برای مقداردهی/پاکسازی SDK.
  • ViewModel در Android از چرخش صفحه جان سالم به در می‌برد و در finish Activity پاک می‌شود — از نشت حافظه جلوگیری می‌کند.
  • SwiftUI @Environment(\.scenePhase) — API یکپارچه برای lifecycle در SwiftUI (active، inactive، background).
  • پردازش صحیح lifecycle مصرف حافظه را 30-40٪ کاهش و از 40٪ کرش‌ها در کار پس‌زمینه جلوگیری می‌کند.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید