App Lifecycle: ما هو، حالات التطبيق في iOS وAndroid

المؤلف: IT Sectr نُشر: 2026-03-02 وقت القراءة: 8 دق
App Lifecycle (دورة حياة التطبيق) هو تسلسل الحالات التي يمر بها التطبيق المحمول من الإطلاق إلى الإنهاء. فهم دورة الحياة أمر بالغ الأهمية لإدارة الموارد وحفظ البيانات وضمان الاستقرار. في iOS، يمر التطبيق بحالات: Not Running → Active → Inactive → Background → Suspended. في Android — عبر onCreate → onStart → onResume → onPause → onStop → onDestroy + onRestart. كل حالة تمنح المطور نافذة لحفظ الحالة أو تحرير الموارد أو الاستعداد للعودة. وفقاً لوثائق Apple، فإن تجاهل أحداث دورة الحياة هو سبب 40 % من الأعطال عند تصغير التطبيق. في IT Sectr، قمنا بتطبيق ProcessLifecycleOwner في Android ونمط AppDelegate في iOS كمعايير إلزامية لجميع المشاريع — مما قلل الأخطاء المتعلقة بالخلفية بنسبة 60 %.

الخلاصة

  • App Lifecycle — مجموعة من حالات التطبيق من الإطلاق إلى الإنهاء، كل منها بإجراءات محددة للمطور.
  • AppDelegate — الفئة المركزية في iOS لمعالجة دورة الحياة: didFinishLaunching، didEnterBackground، willEnterForeground.
  • SceneDelegate — مفوض للمشاهد الفردية (iOS 13+)، يدير دورة حياة كل نافذة في التطبيقات متعددة النوافذ.
  • ProcessLifecycleOwner — مكون Android من AndroidX Lifecycle يتتبع دورة حياة العملية بأكملها.
  • Application.onCreate — أول نقطة دخول لتطبيق Android، يتم استدعاؤه قبل أي Activity.

ما هو App Lifecycle؟

App Lifecycle هو آلة حالات محدودة تصف جميع الحالات الممكنة للتطبيق المحمول والتحولات بينها. تحدد كل حالة ما إذا كان التطبيق يمكنه تنفيذ الكود أو عرض واجهة المستخدم أو استهلاك الموارد. iOS وAndroid لهما نماذج متشابهة ولكن ليست متطابقة — الاختلافات ناتجة عن بنية نظام التشغيل: iOS يستخدم تحكماً صارماً في الذاكرة (حالة suspended)، بينما Android يستخدم إدارة مرنة للعمليات عبر onSaveInstanceState.

في iOS، ترتبط دورة الحياة ارتباطاً وثيقاً بالمقدمة/الخلفية: التطبيق إما نشط أو معلق. في Android، دورة الحياة أكثر تفصيلاً — تمر Activity/نافذة بـ 6+ حالات، وللعملية نفسها دورة حياة إضافية عبر ProcessLifecycleOwner. التطبيقات الحديثة (منذ 2024) تستخدم بشكل متزايد أنماط بنية تعتمد على دورة الحياة: SwiftUI Lifecycle (iOS 16+) عبر بيئة .scenePhase، Compose Lifecycle عبر LifecycleEventObserver. هذه الأنماط تتعامل تلقائياً مع تبديل السياق وتمنع تسرب الذاكرة. وفقاً لـ Google، فإن المعالجة الصحيحة لدورة الحياة في Android تقلل استهلاك الذاكرة بنسبة 30–40 % أثناء العمل في الخلفية.

دورة حياة iOS: AppDelegate وSceneDelegate

في iOS، تتم إدارة دورة حياة التطبيق من خلال الفئة UIApplicationDelegate (AppDelegate). الطرق الرئيسية: application(_:didFinishLaunchingWithOptions:) — التهيئة عند الإطلاق الأول؛ applicationDidBecomeActive — التطبيق مرئي وجاهز للتفاعل؛ applicationWillResignActive — الانتقال إلى الحالة غير النشطة (مكالمة واردة، إغلاق ستارة الإشعارات)؛ applicationDidEnterBackground — التطبيق مخفي، ~5 ثوانٍ لحفظ البيانات؛ applicationWillEnterForeground — العودة من الخلفية؛ applicationWillTerminate — الإنهاء (يُستدعى فقط للتطبيقات القديمة بدون suspended).

بدءاً من iOS 13، قدمت Apple SceneDelegate (UISceneDelegate) لدعم التطبيقات متعددة النوافذ على iPad وmacOS Catalyst. يدير SceneDelegate دورة حياة كل مشهد (نافذة) فردي: scene(_:willConnectTo:options:) — إنشاء المشهد؛ sceneDidBecomeActive — المشهد نشط؛ sceneWillResignActive — المشهد يفقد التركيز؛ sceneDidEnterBackground — المشهد مخفي. يتولى AppDelegate الأحداث العالمية (تحميل البيانات، إشعارات الدفع)، بينما يتولى SceneDelegate حالة واجهة المستخدم لكل نافذة. في SwiftUI، تتم إدارة دورة الحياة من خلال قيمة البيئة @Environment(\.scenePhase): .active، .inactive، .background — مما يوفر واجهة برمجة تطبيقات موحدة لكل من تطبيقات SwiftUI وUIKit.

دورة حياة Android: Application وProcessLifecycleOwner

في Android، تبدأ دورة الحياة بالفئة 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+) يتتبع دورة حياة العملية بأكملها، وليس Activity فردية. يوفر حالتين: ON_RESUME (التطبيق في المقدمة) وON_STOP (التطبيق مخفي). يحل ProcessLifecycleOwner مشكلة «متى انتقل التطبيق إلى الخلفية» على مستوى العملية — وهذا أمر بالغ الأهمية لـ SDK والمكتبات والتطبيقات المعيارية. في Jetpack Compose، تتم إدارة دورة الحياة من خلال LifecycleEventObserver وcollectAsStateWithLifecycle، الذي يعلق تلقائياً جمع البيانات في وضع الخلفية. أضاف Android 14 (API 34) إشعار دورة حياة الخدمة الأمامية عبر Service.onTimeout — يجب أن تكتمل الخدمة في غضون 6 ساعات، وإلا يوقفها النظام قسراً.

مقارنة دورة حياة iOS وAndroid

iOS Android الوصف
Not Running التطبيق لم يتم تشغيله
didFinishLaunching Application.onCreate التهيئة الأولى عند الإطلاق
Active onResume التطبيق مرئي ويقبل الإدخال
Inactive onPause فقدان مؤقت للتركيز (مكالمة، ستارة إشعارات)
Background onStop التطبيق مخفي، يمكن تنفيذ الكود
Suspended الكود لا يُنفذ، الذاكرة محجوزة
Will Terminate onDestroy التطبيق ينتهي

الفرق الرئيسي: iOS ينقل التطبيق قسراً إلى Suspended (يتوقف الكود عن التنفيذ) بعد 5-10 ثوانٍ من الدخول إلى الخلفية. Android يسمح بالعمل في الخلفية (الخدمات، WorkManager) لفترة أطول، ولكن مع قيود من وضع Doze (Android 6+) وقيود الخلفية (Android 12+). ProcessLifecycleOwner في Android هو المكافئ لـ UIApplicationDidEnterBackgroundNotification في iOS، مع الفرق أنه يتم تفعيله عند أي انتقال إلى الخلفية، وليس فقط بعد فقدان التركيز.

أمثلة كود

iOS: AppDelegate مع طرق دورة الحياة

تنفيذ أساسي لـ AppDelegate يعالج جميع حالات دورة الحياة. حفظ البيانات عند الانتقال إلى الخلفية وتحديث واجهة المستخدم عند العودة.

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 هو نقطة دورة الحياة المركزية. applicationDidEnterBackground هو طريقة حرجة: iOS يعطي ~5 ثوانٍ للحفظ. applicationDidBecomeActive — قم بتحديث واجهة المستخدم، أعد تشغيل الرسوم المتحركة. بالنسبة لـ SceneDelegate (iOS 13+)، يتم توزيع منطق دورة الحياة عبر المشاهد: sceneDidBecomeActive / sceneDidEnterBackground تديران النوافذ الفردية.

iOS: SceneDelegate (iOS 13+)

SceneDelegate لتطبيقات iPad متعددة النوافذ. كل مشهد له دورة حياة خاصة به، مستقلة عن النوافذ الأخرى.

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 يدير دورة حياة مشهد فردي. sceneDidBecomeActive / sceneDidEnterBackground هما معادلا طرق AppDelegate لنافذة محددة. يُستدعى sceneDidDisconnect عند إغلاق مشهد (أغلق المستخدم نافذة على iPad). للتوافق مع iOS 12 والإصدارات الأقدم، يجب على AppDelegate تكرار منطق SceneDelegate. في iOS 17+، يمكنك استخدام @Observable للإيقاف/الاستئناف التلقائي للمهام بناءً على scenePhase.

Android: Application مع ProcessLifecycleOwner

يتتبع ProcessLifecycleOwner متى يكون التطبيق في المقدمة/الخلفية على مستوى العملية. هذا هو النهج الأمثل لإدارة دورة الحياة العالمية.

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 يُفعّل عندما يصبح التطبيق مرئياً (المقدمة)، ON_STOP — عندما يكون مخفياً تماماً (الخلفية). على عكس دورة حياة Activity، فإن ProcessLifecycleOwner غير مرتبط بشاشة محددة. بالنسبة لـ Jetpack Compose، استخدم LifecycleResumeEffect أو collectAsStateWithLifecycle بدلاً من المراقبة اليدوية.

Android: دورة حياة Activity مع ViewModel

ViewModel + Lifecycle هي البنية الصحيحة لنظام Android لإدارة دورة الحياة. يتم تنظيف 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 يبقى بعد تدوير الشاشة ويُدمر فقط عند إنهاء Activity. onCleared() هو المكان لتحرير الموارد وإلغاء الاشتراك من التدفقات. LiveData يوقف المراقبة تلقائياً عند onPause ويستأنفها عند onResume — وهذا يوفر حماية ضد التسرب والأعطال أثناء العمل في الخلفية. في Compose، استخدم collectAsStateWithLifecycle() لنفس الغرض.

الأسئلة الشائعة

ماذا يحدث عندما يصغر المستخدم تطبيق iOS؟

عند التصغير، ينتقل التطبيق من نشط إلى غير نشط (لفترة وجيزة)، ثم إلى الخلفية. بعد بضع ثوانٍ، قد ينقله النظام إلى suspended — يتوقف الكود عن التنفيذ، الذاكرة محجوزة. عندما تكون الذاكرة منخفضة، ينهي النظام التطبيق المعلق (لا يتم استدعاء willTerminate). احفظ بياناتك في applicationDidEnterBackground — هذه هي آخر نقطة مضمونة للحفظ.

هل أحتاج إلى معالجة جميع حالات App Lifecycle؟

الحد الأدنى الإلزامي: applicationDidEnterBackground — حفظ بيانات المستخدم؛ applicationWillEnterForeground — تحديث واجهة المستخدم؛ في Android onPause — إيقاف الرسوم المتحركة/أجهزة الاستشعار. ProcessLifecycleOwner يبسط المعالجة: onResume — onPause للمقدمة، onStart — onStop للرؤية. قم بمعالجة الحالات الأخرى حسب الحاجة — ليست كل الحالات حرجة لكل تطبيق.

كيف يختلف SceneDelegate عن AppDelegate؟

AppDelegate هو المفوض العالمي للتطبيق بأكمله (الإطلاق، الانتقال إلى الخلفية). SceneDelegate (iOS 13+) يدير دورة حياة نافذة فردية (مشهد) — في تطبيقات iPad متعددة النوافذ، كل مشهد له دورة حياة خاصة به. بالنسبة لـ iOS 12 والإصدارات الأقدم، تتم إدارة دورة الحياة بالكامل عبر AppDelegate. مع iPadOS 16+، SceneDelegate إلزامي لـ Stage Manager.

ما هو ProcessLifecycleOwner في Android؟

ProcessLifecycleOwner هو مكون من AndroidX Lifecycle يتتبع دورة حياة التطبيق بأكمله (العملية)، وليس Activity فردية. يوفر حدثين رئيسيين: ON_RESUME (التطبيق في المقدمة) وON_STOP (التطبيق في الخلفية). يُستخدم لتهيئة/تنظيف SDK والتحليلات ومراقبي الشبكة — أي شيء يجب أن يستجيب لانتقال التطبيق إلى الخلفية، بغض النظر عن الشاشة الحالية.

كيفية معالجة دورة الحياة في 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+) يدير دورة حياة كل مشهد بشكل منفصل — إلزامي لتطبيقات iPad متعددة النوافذ.
  • Android ProcessLifecycleOwner هو مراقب عالمي لدورة حياة العملية لتهيئة/تنظيف SDK.
  • ViewModel في Android يبقى بعد تدوير الشاشة ويتم تنظيفه عند إنهاء Activity — يمنع تسرب الذاكرة.
  • SwiftUI @Environment(\.scenePhase) يوفر واجهة برمجة تطبيقات موحدة لدورة الحياة في SwiftUI (active، inactive، background).
  • المعالجة الصحيحة لدورة الحياة تقلل استهلاك الذاكرة بنسبة 30-40% وتمنع 40% من الأعطال أثناء العمل في الخلفية.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا