LifecycleOwner — ما هو، واجهة Jetpack والاشتراك في الأحداث

المؤلف: IT Sectr نُشر: 2026-03-06 وقت القراءة: 9 دق

LifecycleOwner هي واجهة رئيسية من مكتبة Android Jetpack تعلن أن الكائن يمتلك دورة حياة وتوفر الوصول إليها عبر الطريقة getLifecycle(). تشكل أساس هندسة المكونات في تطبيقات Android الحديثة، مما يسمح بفصل منطق دورة الحياة عن التنفيذ المحدد لـ Activity أو Fragment. وفقًا لـ Google I/O 2024، أكثر من 85% من المشاريع الجديدة على Android تستخدم LifecycleOwner لإدارة الاشتراكات ومنع تسرب الذاكرة. هذه الواجهة هي أساس LiveData و ViewModel ومكونات Jetpack الأخرى، مما يضمن تنفيذ آمن للكود فقط عندما يكون المكون في حالة نشط.

النقاط الرئيسية

  • LifecycleOwner — واجهة Jetpack توفر الوصول إلى كائن Lifecycle
  • مطبقة بالافتراضي في Activity و Fragment من AndroidX AppCompat
  • تسمح بالاشتراك في الأحداث عبر LifecycleObserver و DefaultLifecycleObserver
  • تمنع تسرب الذاكرة — يلغي المراقبون الاشتراك تلقائيًا عند الإتلاف
  • تستخدم في ViewModel و LiveData ومكونات Jetpack الأخرى للعمل الآمن

ما هو LifecycleOwner؟

LifecycleOwner هي واجهة من حزمة androidx.lifecycle تحتوي على طريقة واحدة هي getLifecycle()، والتي تعيد كائن Lifecycle. يتبع هذا الكائن الحالة الحالية للمكون (CREATED، STARTED، RESUMED، DESTROYED) ويخطر جميع المراقبين المشتركين عند تغيرها. LifecycleOwner هي جزء من Architecture Components وتندرج في مكتبة lifecycle-runtime.

الهدف الرئيسي للواجهة هو توحيد الوصول إلى دورة الحياة. قبل Jetpack، كان المطورون يشتركون ددويًا في onStart ويلغون الاشتراك في onStop، ما أدى إلى تكرار الكود والأخطاء. يحل LifecycleOwner هذه المشكلة من خلال توفير آلية موحدة لجميع مكونات Android. بدلاً من استدعاء طرق دورة الحياة صراحة، يشترك المطور في Lifecycle مرة واحدة، وتصل الإشعارات تلقائيًا.

تُصرح الواجهة في Kotlin كواجهة وظيفية بطريقة مجردة واحدة:

kotlin
interface LifecycleOwner {
    val lifecycle: Lifecycle
}

بفضل الطابع الوظيفي للواجهة، من السهل تنفيذها باستخدام مفوض أو lambda. هذا مفيد بشكل خاص لإنشاء Custom Views وفئات ViewModel التي تحتاج إلى الاستجابة لتغيرات دورة حياة المضيف. يوفر كائن Lifecycle المحصل عليه من getLifecycle() طرقي addObserver و removeObserver لإدارة الاشتراكات.

كيف يعمل LifecycleOwner

LifecycleOwner يعمل بالاشتراك مع فئتين رئيسيتين: Lifecycle و LifecycleObserver. يخزن Lifecycle الحالة الحالية للمكون كتعداد State (INITIALIZED، CREATED، STARTED، RESUMED، DESTROYED) ويتبع الانتقالات بينها. عندما تتغير الحالة، يخطر Lifecycle جميع المراقبين المسجلين من خلال استدعاء الطرق الموسومة المناسبة. يطلق على هذه الآلية اسم “واعية بدورة الحياة” — يتم تنفيذ الكود فقط عندما يكون المكون في حالة مناسبة.

تعتمد آلية توصيل الأحداث على نمط Observer. يعمل LifecycleOwner كـ Observable، وتعمل تطبيقة LifecycleObserver كـ Observer. عندما تغير Activity أو Fragment حالتها (onCreate → onStart → onResume → onPause → onStop → onDestroy)، تخطر Lifecycle عبر آلية ReportFragment الداخلية، التي تضاف تلقائيًا إلى نظام AndroidX. لا يحتاج المطور إلى استدعاء طرق Lifecycle يدويًا — كل شيء يحدث تلقائيًا.

حالة Lifecycleالحدثطريقة دورة الحياة في Android
INITIALIZEDقبل onCreate
CREATEDON_CREATEonCreate
STARTEDON_STARTonStart
RESUMEDON_RESUMEonResume
STARTEDON_PAUSEonPause
CREATEDON_STOPonStop
DESTROYEDON_DESTROYonDestroy

تفصيل مهم: Lifecycle يضمن توصيل حدثي ON_STOP و ON_DESTROY حتى في حال تعطل العملية بشكل غير متوقع. هذا يجعل LifecycleOwner أداة موثوقة لتحرير الموارد الحرجة. للحفاظ على الحالة العادية، يوصى باستخدام SavedStateHandle في ViewModel، ولكن LifecycleOwner يوفر مستوى أساسيًا من الأمان.

LifecycleObserver و DefaultLifecycleObserver

هناك طريقتان للاشتراك في أحداث LifecycleOwner: LifecycleObserver الكلاسيكي بالتعليقات و DefaultLifecycleObserver الحديث بالطرق الصريحة. توصي Google بالنهج الثاني منذ 2022، حيث يوفر أمانًا أفضل للأنواع ويتجنب الانعكاس المستخدم في النهج القائم على التعليقات. يتطلب DefaultLifecycleObserver Java 8+ أو Kotlin وهو الخيار المفضل للمشاريع الجديدة.

مثال على الاشتراك عبر DefaultLifecycleObserver:

kotlin
class MyObserver : DefaultLifecycleObserver {
    override fun onStart(owner: LifecycleOwner) {
        // تشغيل تتبع GPS فقط عندما يكون المكون نشطًا
        startLocationUpdates()
    }

    override fun onStop(owner: LifecycleOwner) {
        // إيقاف آمن عند الانتقال إلى الخلفية
        stopLocationUpdates()
    }
}

// الاتصال:
lifecycleOwner.lifecycle.addObserver(MyObserver())

كل طريقة في DefaultLifecycleObserver تستقبل LifecycleOwner كوسيطة. يسمح هذا للمراقب بالوصول إلى سياق المكون المنفذ دون الحاجة إلى تمريره بشكل منفصل. هذا النهج يجعل الكود أكثر نمطية وقابلية للاختبار — المراقب لا يعتمد على تطبيق محدد لـ Activity أو Fragment، بل يعمل مع التجريد LifecycleOwner.

نهج LifecycleObserver القائم على التعليقات

الطريقة القديمة باستخدام التعليق @OnLifecycleEvent لا تزال موجودة في المشاريع القديمة، ولكن لا يوصى باستخدامها للكود الجديد. الانعكاس المطلوب لمعالجة التعليقات يضيف عبئاً وقد يؤدي إلى أخطاء لا تُكتشف في وقت الترجمة. توصي Google رسميًا بالترحيل إلى DefaultLifecycleObserver.

kotlin
// نهج قديم — غير موصى به للمشاريع الجديدة
class MyLegacyObserver : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onStart() {
        startLocationUpdates()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onStop() {
        stopLocationUpdates()
    }
}

لنهج التعليقات عيب كبير: عدم التحكم في عمر المراقب. إذا نسي المطور إلغاء اشتراك المراقب عند إتلاف LifecycleOwner، يبقى كائن المراقب في الذاكرة حتى يعمل مجمع القمامة. يحل DefaultLifecycleObserver هذه المشكلة — المراقب مرتبط بـ Lifecycle ويلغي اشتراكه تلقائيًا عند الانتقال إلى حالة DESTROYED.

LifecycleOwner في Activity و Fragment

منذ AppCompat 1.1.0 و AndroidX Fragment 1.2.0، جميع كيانات Activity و Fragment التي ترث AppCompatActivity أو Fragment هي تلقائيًا LifecycleOwners. هذا يعني أن الطريقة getLifecycle() متاحة بالافتراضي، والاشتراك في أحداث دورة الحياة يعمل دون إعداد إضافي. يكتفي المطور باستدعاء lifecycle.addObserver() من أي مكان في Activity أو Fragment.

لننظر إلى مثال دمج LifecycleOwner في Activity:

kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(LocationObserver(this))
    }
}

في هذا المثال، lifecycle هي خاصية تمديد متاحة بفضل AndroidX Activity. سيتلقى LocationObserver تلقائيًا إشعارات حول البدء (ON_START) والإيقاف (ON_STOP) لـ Activity. عند تدوير الشاشة، يتم إشعار المراقب بـ ON_DESTROY ثم ON_CREATE، مما يسمح بمعالجة تغييرات التهيئة بشكل صحيح دون كود إضافي.

LifecycleOwner في Fragment

Fragment ينفذ LifecycleOwner عبر واجهته، و Lifecycle الخاص به مرتبط بدورة حياة Fragment، ليس بدورة حياة Activity الأصلية. هذا مهم: ينتقل Lifecycle لـ Fragment إلى DESTROYED عندما يتم إزالة Fragment من المعاملة، بينما قد تظل Activity في RESUMED. يسمح هذا الاختلاف للمراقبين بالاشتراك بشكل منفصل في دورة حياة كل مكون.

kotlin
class MyFragment : Fragment() {
    private val uiStateObserver = UiStateObserver()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        lifecycle.addObserver(uiStateObserver)
    }
}

ميزة مهمة لاستخدام LifecycleOwner في Fragment هي إلغاء الاشتراك التلقائي عند انتقال Fragment إلى DESTROYED. هذا مناسب بشكل خاص لـ ViewPager، حيث يمكن إنشاء وتدمير Fragments ديناميكيًا. كانت الإدارة اليدوية للاشتراكات في هذا السيناريو ستكون معقدة جدًا وعرضة للأخطاء.

إنشاء LifecycleOwner مخصص

يمكن تنفيذ واجهة LifecycleOwner في أي فئة لديها دورة حياة. هذا مفيد لـ Custom Views و Services وحتى ViewModel في بعض الحلول المعمارية. توفر Google فئة المساعدة LifecycleRegistry، التي تدير حالة Lifecycle وتولد الأحداث. يحتاج المطور إلى استدعاء طرق LifecycleRegistry المناسبة يدويًا عند تغير حالة المكون.

مثال تنفيذ LifecycleOwner في Custom View:

kotlin
class MyCustomView(
    context: Context,
    attrs: AttributeSet?
) : FrameLayout(context, attrs), LifecycleOwner {

    private val lifecycleRegistry = LifecycleRegistry(this)

    override val lifecycle: Lifecycle
        get() = lifecycleRegistry

    fun onStart() {
        lifecycleRegistry.setCurrentState(Lifecycle.State.STARTED)
    }

    fun onStop() {
        lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED)
    }
}

في هذا المثال، LifecycleRegistry يعمل كمخزن للحالة. يجب أن تستدعي المكونة الأصلية (مثل Activity) طريقتي onStart/onStop عندما تصبح Custom View مرئية أو تختفي. يحسب LifecycleRegistry تلقائيًا الأحداث المطلوبة للانتقال بين الحالات ويخطر جميع المراقبين المشتركين.

عند تنفيذ LifecycleOwner مخصص، من المهم اتباع القاعدة: يجب تحديث حالة LifecycleRegistry في آخر الطريقة المناسبة لدورة الحياة، بعد جميع العمليات الأخرى. يضمن هذا أن يتلقى المراقبون إشعارًا عندما يكون المكون جاهزًا بالكامل للحالة الجديدة. استخدام LifecycleRegistry.createUnsafe كبديل ممكن أيضًا، ولكنه يتطلب الحذر مع الخيوط.

LifecycleOwner في مكونات Jetpack

LifecycleOwner هو أساس عدة مكونات رئيسية في Android Jetpack. LiveData تستخدم LifecycleOwner لتحديد الحالة النشطة وإلغاء الاشتراك تلقائيًا عند إتلاف المكون. ViewModel لا تنفذ LifecycleOwner مباشرة، ولكن يمكنها الحصول على Lifecycle عبر SavedStateHandle. Navigation Component تستخدم LifecycleOwner لإدارة الاشتراكات في NavBackStackEntry. يساعد فهم هذه العلاقة في بناء هندسة التطبيق على أساس متين.

تفاعل LiveData مع LifecycleOwner:

kotlin
class ExampleActivity : AppCompatActivity() {
    private val viewModel: ExampleViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel.userData.observe(this) { data ->
            // this — LifecycleOwner (Activity)
            // يتم تنفيذ الكود فقط عندما تكون Activity في حالة RESUMED
            updateUI(data)
        }
    }
}

تتطلب LiveData كائن LifecycleOwner في الطريقة observe() لأنها تضمن أن تحديثات واجهة المستخدم تحدث فقط في الحالة النشطة. إذا كانت Activity في الخلفية، تحتفظ LiveData بآخر قيمة ولكن لا تخطر المراقب. عند العودة إلى RESUMED، يتلقى المراقب القيمة الحالية دون طلبات إضافية للشبكة أو قاعدة البيانات.

DataBinding تستخدم أيضًا LifecycleOwner لربط الحقول القابلة للمراقبة بدورة حياة Activity أو Fragment. يساعد هذا في تجنب تسرب الذاكرة في مزيج ViewModel + DataBinding — جميع الاشتراكات تُنظف تلقائيًا عند إتلاف LifecycleOwner. هذا النهج يجعل الكود تصريحيًا وآمنًا.

أفضل الممارسات

يتطلب الاستخدام الصحيح لـ LifecycleOwner اتباع عدة قواعد رئيسية. الأولى والأهم: قم دائمًا باشتراك المراقب في onCreate/onViewCreated، وليس لاحقًا. يضمن هذا أن يتلقى المراقب حالة Lifecycle الأولية (CREATED بعد onCreate) ولا يفوته أي أحداث. القاعدة الثانية: استخدم DefaultLifecycleObserver بدلاً من النهج القائم على التعليقات لجميع المشاريع الجديدة.

  • لا تخزن مرجعًا لـ LifecycleOwner في حقول ثابتة أو كيانات مفردة — هذا يتسبب في تسريب Activity بأكملها
  • تحقق من حالة Lifecycle عبر getCurrentState() قبل تنفيذ العمليات الحساسة للحالة
  • لا تنشأ مراقبين داخل lambdas — كل إعادة تركيب تنشئ كائنًا جديدًا، والمراقبون القدماء لن يلغوا اشتراكهم تلقائيًا
  • استخدم repeatOnLifecycle للكوروتين — يبدأ البلوك عند الدخول إلى الحالة المحددة ويلغى عند الخروج منها
  • لا تستدع setCurrentState على LifecycleRegistry من خيط خلفي — هذا ينتهك ضمان الخيط الواحد لدورة الحياة

النهج الحديث للعمل مع الكوروتين و LifecycleOwner هو امتداد repeatOnLifecycle:

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.flow.collect { value ->
            updateUI(value)
        }
    }
}

يضمن هذا النمط أن collect على Flow نشط فقط في حالة STARTED أو RESUMED. عند الانتقال إلى STOPPED، يتم إلغاء التجميع تلقائيًا، وعند العودة إلى STARTED يعاد تشغيله. يستبدل repeatOnLifecycle إلغاء الاشتراك اليدوي من Flow في Fragments وهو النهج الموصى به من Google للعمل مع تدفقات البيانات غير المتزامنة في مكونات واجهة المستخدم.

توصية مهمة أخرى: لا تفرط في استخدام LifecycleObserver للمنطق غير المرتبط بدورة الحياة. إذا كان المكون يحتاج إلى تنفيذ إجراء في حالة محددة ولكنه لا يتطلب إلغاء الاشتراك عند الإتلاف، فمن الأفضل استخدام استدعاءات صريحة للطرق في onStart/onStop. LifecycleObserver مبرر للمكونات طويلة العمر (LocationListener، SensorManager) حيث تكون الإدارة اليدوية للاشتراكات معقدة وعرضة للأخطاء.

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

ما الفرق بين LifecycleOwner و Lifecycle؟

LifecycleOwner هي واجهة تعلن أن الكائن لديه دورة حياة. Lifecycle هو فئة تخزن الحالة الحالية وتدير المراقبين. توفر LifecycleOwner Lifecycle عبر getLifecycle().

هل يجب إلغاء اشتراك LifecycleObserver يدويًا؟

لا، Lifecycle يلغي اشتراك جميع المراقبين تلقائيًا عند الانتقال إلى DESTROYED. هذه واحدة من المزايا الرئيسية لـ LifecycleOwner — لا يحتاج المطور إلى استدعاء removeObserver يدويًا في onDestroy.

كيف يعمل LifecycleOwner في Fragment؟

Fragment ينفذ LifecycleOwner عبر واجهة الفراغمنتات من AndroidX. يرتبط Lifecycle الخاص به بدورة حياة Fragment بشكل منفصل عن Activity. يسمح هذا للمراقب بالتفاعل تحديدًا مع أحداث Fragment، ليس مع أحداث Activity الأصلية.

هل يمكن تنفيذ LifecycleOwner في Custom View؟

نعم، يتم استخدام LifecycleRegistry لهذا الغرض. يجب على Custom View تنفيذ واجهة LifecycleOwner وتحديث حالة LifecycleRegistry يدويًا عند تغير الرؤية أو عند الارتباط بالنافذة.

لماذا أحتاج إلى LifecycleOwner إذا كان لدي CoroutineScope؟

LifecycleOwner يحل مشكلة مختلفة: إدارة الاشتراكات في أحداث دورة الحياة، ليس إلغاء الكوروتين. للكوروتين، يتم استخدام lifecycleScope، الذي يلغي تلقائيًا الكوروتين المشغلة عند إتلاف LifecycleOwner.

الملخص

  • LifecycleOwner — واجهة Android Jetpack للوصول إلى دورة الحياة عبر getLifecycle()
  • مطبقة بالافتراضي في AppCompatActivity و Fragment من AndroidX
  • تدعم DefaultLifecycleObserver — طريقة اشتراك حديثة آمنة للأنواع
  • تلغي اشتراك المراقبين تلقائيًا عند الانتقال إلى DESTROYED، ممنعة تسرب الذاكرة
  • تستخدم في LiveData، DataBinding و Navigation Component كأساس lifecycle-aware
  • تسمح بإنشاء LifecycleOwners مخصصة عبر LifecycleRegistry لـ Custom Views و Services
  • البديل الحديث — repeatOnLifecycle للكوروتين و Flow، ليحل محل الاشتراك اليدوي

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

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

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

اقرأ أيضًا