مراحل النشاط في Jetpack Compose   جزء من Android Jetpack.

تنفِّذ المكوّنات التي تراعي مراحل النشاط إجراءات استجابةً لتغيير في حالة مراحل نشاط العنصر المضيف. يوفر العنصر androidx.lifecycle.compose واجهات برمجة تطبيقات مخصّصة تعمل على تنظيف الموارد تلقائيًا عندما تغادر الشاشة أو عندما ينتقل التطبيق إلى الخلفية.

تشمل واجهات برمجة التطبيقات الرئيسية ما يلي:

توفّر عمليات الدمج هذه نقاط ربط ملائمة لإدارة دورات الحياة ضمن التسلسل الهرمي لـ Compose. يوضّح هذا المستند كيفية استخدامها في تطبيقك.

جمع بيانات حالة مراحل النشاط باستخدام المسارات

تعرض Lifecycle السمة currentStateFlow التي توفّر Lifecycle.State الحالي كـ StateFlow في Kotlin. يمكنك جمع هذه Flow كـ State. يتيح ذلك لتطبيقك قراءة التغييرات في Lifecycle أثناء الإنشاء.

val lifecycleOwner = LocalLifecycleOwner.current
val stateFlow = lifecycleOwner.lifecycle.currentStateFlow

val currentLifecycleState by stateFlow.collectAsState()

يمكن الوصول إلى المثال السابق باستخدام الوحدة lifecycle-common. تتوفّر الطريقة currentStateAsState() في الوحدة lifecycle-runtime-compose، ما يتيح لك قراءة حالة Lifecycle الحالية بسهولة باستخدام سطر واحد. يوضّح المثال التالي ذلك:

val lifecycleOwner = LocalLifecycleOwner.current
val currentLifecycleState = lifecycleOwner.lifecycle.currentStateAsState()

تنفيذ الرمز البرمجي عند وقوع أحداث مراحل النشاط

بدلاً من إنشاء فئة منفصلة تنفّذ DefaultLifecycleObserver وإضافتها يدويًا إلى مراحل النشاط، يمكنك التعريف بمنطق مراحل النشاط مضمّنًا باستخدام تأثيرات معيّنة. تتيح لك LifecycleEffects تشغيل كتلة برمجية عندما يحدث Lifecycle.Event معيّن مباشرةً ضمن المقطوعة الموسيقية.

LifecycleEventEffect

استخدِم LifecycleEventEffect لتنفيذ مجموعة من الرموز البرمجية عند وقوع حدث معيّن. هذا الخيار هو الأفضل للأحداث التي تحدث مرة واحدة، مثل التسجيل أو الإحصاءات، حيث لا تكون هناك حاجة إلى النجاح أو نتيجة فورية.

@Composable
fun AnalyticsTracker(screenName: String) {
    // Log an event when the app receives ON_RESUME (e.g. comes to foreground)
    LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
        Analytics.logView(screenName)
    }
}

LifecycleStartEffect

بالنسبة إلى عمليات البدء/الإيقاف المقترنة التي يجب تنفيذها أثناء تشغيل التطبيق (مرئيًا) وإيقافه (في الخلفية)، استخدِم LifecycleStartEffect.

على غرار المؤثرات الأخرى في Compose (مثل LaunchedEffect)، تقبل الدالة LifecycleStartEffect المفاتيح. عندما يتغير المفتاح، يتم تشغيل الكتلة مرة أخرى.

عندما يحدث حدث Lifecycle.Event.ON_STOP أو يخرج التأثير من التركيب، يتم تنفيذ كتلة onStopOrDispose لتنظيف أي عمل كان جزءًا من كتلة البدء.

@Composable
fun LocationMonitor(locationManager: LocationManager) {
    // Starts monitoring when ON_START is dispatched
    // Stops monitoring when ON_STOP is dispatched
    //   (or the composable leaves the screen)
    LifecycleStartEffect(locationManager) {
        val listener = LocationListener { location ->
            /* update UI */
        }
        locationManager.requestLocationUpdates(listener)
        // The cleanup block automatically runs on ON_STOP or on disposal
        onStopOrDispose {
            locationManager.removeUpdates(listener)
        }
    }
}
.

للحصول على معلومات حول الأنواع الأخرى من التأثيرات الجانبية، راجِع التأثيرات الجانبية في Compose.

LifecycleResumeEffect

تعمل السمة LifecycleResumeEffect بالطريقة نفسها التي تعمل بها السمة LifecycleStartEffect، ولكنّها مرتبطة بالحدث Lifecycle.Event.ON_RESUME بدلاً من ذلك. ويوفّر أيضًا كتلة onPauseOrDispose تنفّذ عملية التنظيف عند إرسال ON_PAUSE أو عند مغادرة العنصر القابل للإنشاء الشاشة.

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

@Composable
fun CameraPreview(cameraController: CameraController) {
    LifecycleResumeEffect(cameraController) {
        cameraController.startPreview()

        onPauseOrDispose {
            cameraController.stopPreview()
        }
    }
}

الوصول إلى LifecycleOwner

في Compose، تتوفّر LifecycleOwner ضمنيًا من خلال CompositionLocal التي تحمل الاسم LocalLifecycleOwner. بشكل تلقائي، يوفّر المضيف الجذر للتسلسل الهرمي للمقطوعة الموسيقية هذا المالك.

val lifecycleOwner = LocalLifecycleOwner.current

بالنسبة إلى العديد من التطبيقات، يكون فحص المالك التلقائي أو تمريره إلى التأثيرات المتوافقة مع مراحل النشاط كافيًا. ومع ذلك، بالنسبة إلى التنقّل المخصّص أو التصاميم المعقّدة، قد تحتاج إلى إنشاء LifecycleOwner خاص بك لتحديد نطاق حالات مراحل النشاط في أقسام معيّنة من واجهة المستخدم. على سبيل المثال، تنفّذ مكتبات التنقّل (مثل Navigation 3) ذلك تلقائيًا لمنح كل شاشة فردية دورة حياتها الخاصة.

إنشاء LifecycleOwner مخصّص

تتيح لك واجهة برمجة التطبيقات rememberLifecycleOwner() إنشاء LifecycleOwner مخصّص وتذكّره. ويفيد ذلك بشكل خاص في المكوّنات، مثل HorizontalPager، حيث تريد أن تكون الصفحة المرئية والثابتة فقط هي RESUMED، مع ضبط maxState على STARTED للصفحات المجاورة التي تقع خارج الشاشة.

val pagerState = rememberPagerState(pageCount = { 10 })

HorizontalPager(state = pagerState) { pageNum ->
    val pageLifecycleOwner = rememberLifecycleOwner(
        maxState = if (pagerState.settledPage == pageNum) {
            Lifecycle.State.RESUMED
        } else {
            Lifecycle.State.STARTED
        }
    )

    CompositionLocalProvider(LocalLifecycleOwner provides pageLifecycleOwner) {
        // Your pages here. Their lifecycle-aware components respect the
        // custom maxState defined above.
    }
}

لمزيد من المعلومات حول CompositionLocal، راجِع البيانات ذات النطاق المحلي باستخدام CompositionLocal.

أفضل الممارسات للمكوّنات التي تراعي مراحل النشاط

  • يجب أن تكون عناصر التحكّم في واجهة المستخدم بسيطة قدر الإمكان. ولا يجب أن يحاولوا الحصول على بياناتهم الخاصة، بل عليهم استخدام ViewModel لتنفيذ ذلك، ومراقبة عنصر StateFlow لعرض التغييرات في واجهة المستخدم.
  • حاوِل كتابة واجهات مستخدم مستندة إلى البيانات، حيث تكون مسؤولية وحدة التحكّم في واجهة المستخدم هي تعديل واجهة المستخدم عند تغيُّر البيانات، أو إرسال إشعارات بشأن إجراءات المستخدم إلى ViewModel.
  • ضَع منطق البيانات في فئة ViewModel. يجب أن يعمل ViewModel كأداة ربط بين وحدة التحكّم في واجهة المستخدم وبقية تطبيقك. ومع ذلك، يجب الانتباه إلى أنّ ViewModel ليس مسؤولاً عن جلب البيانات (على سبيل المثال، من شبكة). بدلاً من ذلك، يجب أن يستدعي ViewModel المكوّن المناسب لجلب البيانات، ثم يعرض النتيجة مرة أخرى لوحدة التحكّم في واجهة المستخدم.
  • استخدِم أنماط "كوروتين" في Kotlin لإدارة المهام الطويلة الأمد والعمليات الأخرى التي يمكن تنفيذها بشكل غير متزامن.
  • احتفِظ بمنطق البدء/الإيقاف داخل العنصر القابل للإنشاء الذي يحتاج إليه فعليًا. بهذه الطريقة، تتم إزالة منطق الربط تلقائيًا إذا تمت إزالة عنصر في واجهة المستخدم المحدّد من الشاشة (على سبيل المثال، داخل رسم بياني للتنقّل أو عندما تكون إمكانية الظهور مشروطة).
  • استخدام collectAsStateWithLifecycle للبيانات لا تبدأ عملية جمع البيانات أو توقفها يدويًا استنادًا إلى أحداث مراحل النشاط.Flow بدلاً من ذلك، استخدِم collectAsStateWithLifecycle لتحويل عمليات البث إلى حالة واجهة المستخدم بكفاءة. يساعد ذلك في توفير شحن البطارية والموارد لأنّه يتم إيقاف Flow مؤقتًا عندما يكون التطبيق يعمل في الخلفية.

لمزيد من المعلومات عن Flow، يُرجى الاطّلاع على أنواع أخرى من الحالات المتوافقة.

حالات استخدام المكوّنات التي تراعي مراحل النشاط

يمكن أن تسهّل عليك المكوّنات التي تراعي مراحل النشاط إدارة مراحل النشاط في مجموعة متنوعة من الحالات. في ما يلي بعض الأمثلة:

  • التبديل بين تحديثات الموقع الجغرافي التقريبية والدقيقة استخدِم LifecycleStartEffect لتفعيل تحديثات الموقع الجغرافي الدقيقة أثناء ظهور تطبيقك (ON_START)، ولإزالة أداة معالجة البيانات تلقائيًا أو التبديل إلى تحديثات الموقع الجغرافي التقريبية عندما يكون التطبيق في الخلفية (ON_STOP).
  • إيقاف تخزين الفيديو مؤقتًا وبدء تخزينه استخدِم LifecycleResumeEffect لتأجيل تشغيل الفيديو الفعلي إلى حين يصبح التطبيق في المقدّمة بالكامل وتفاعليًا (ON_RESUME)، وللتأكّد من إيقاف التشغيل مؤقتًا وإتاحة الموارد عندما يتم نقل التطبيق إلى الخلفية (ON_PAUSE).
  • بدء البث عبر الشبكة وإيقافه استخدِم collectAsStateWithLifecycle لمراقبة مصادر البيانات المتواصلة (مثل Kotlin Flow من مقبس شبكة). ويتيح لك ذلك تحديث البيانات مباشرةً أثناء تشغيل التطبيق في المقدّمة، كما يلغي عملية الجمع تلقائيًا عند تشغيل التطبيق في الخلفية.
  • إيقاف المهام التي تتطلّب موارد كثيرة مؤقتًا واستئنافها استخدِم LifecycleResumeEffect للتعامل مع إيقاف التحديثات المرئية الكبيرة مؤقتًا عندما يكون التطبيق في الخلفية، واستئنافها بعد أن يصبح التطبيق في المقدّمة.

التعامل مع أحداث ON_STOP بأمان

تم تصميم ميزة "إنشاء" للتعامل مع أحداث ON_STOP بأمان.

  • الحالة آمنة: يمكنك تعديل MutableState (على سبيل المثال، باستخدام uiState.value = ...) في أي وقت، حتى عندما يكون التطبيق يعمل في الخلفية. تنتظر Compose إلى أن يصبح التطبيق مرئيًا لعرض التغييرات.
  • عمليات التنظيف التلقائية: باستخدام تأثيرات مثل LifecycleStartEffect، يتم تنفيذ عملية التنظيف في الحظر (onStopOrDispose) بالضبط عندما تنتقل دورة الحياة إلى STOPPED. ويمنعك ذلك من الاحتفاظ بموارد كبيرة (مثل الكاميرا أو الموقع الجغرافي) أثناء تشغيل التطبيق في الخلفية.

لمزيد من المعلومات عن MutableState، اطّلِع على الحالة وJetpack Compose.

مراجع إضافية

لمزيد من المعلومات حول التعامل مع مراحل النشاط باستخدام المكوّنات التي تراعي مراحل النشاط، يُرجى الرجوع إلى المراجع الإضافية التالية.

مشاهدة المحتوى