onResume — أساسيات، التفاعل مع المستخدم في أندرويد

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

onResume هي طريقة من دورة حياة أندرويد يتم استدعاؤها عندما ينتقل النشاط أو الجزء إلى المقدمة ويحصل على تركيز الإدخال. في هذه الحالة، تكون الشاشة جاهزة للتفاعل مع المستخدم: جميع أحداث اللمس وضغطات المفاتيح والإيماءات تُوجه إلى هذا المكون. onResume هي حالة العمل للنشاط، حيث تقضي التطبيق معظم وقته. هنا يتم فتح الكاميرا، بدء تشغيل الفيديو، بدء التعرف على الكلام، وتسجيل مستمعي الاستشعار الذين يتطلبون وصولاً حصرياً. لمزيد من المعلومات حول دورة حياة النشاط الكاملة، اقرأ المقالة Activity Lifecycle.

الرئيسية

  • onResume — النشاط في المقدمة مع تركيز الإدخال؛ يُستدعى بعد onStart أو بعد العودة من مربع حوار
  • الموارد الحصرية — الكاميرا والميكروفون والتقاط الفيديو تُفتح في onResume وتُغلق في onPause
  • زوج onResume/onPause — الموارد التي تتطلب تركيزاً كاملاً تُدار بهذا الزوج؛ تُسجل في onResume، وتُحرر في onPause
  • onResume مقابل onStart — onStart = الرؤية، onResume = التفاعل؛ مربع الحوار يلغي onResume لكن لا يلغي onStart
  • التوقيت — يجب أن يكون onResume سريعاً؛ العمليات الطويلة هنا تؤخر استجابة الواجهة
  • Fragment.onResume — يُستدعى بعد Activity.onResume، عندما يكون الجزء جاهزاً للتفاعل
  • onResume في Jetpack — lifecycleScope و LiveData يستخدمان onResume للإدارة التلقائية للاشتراكات

أساسيات طريقة onResume في أندرويد

onResume — الطريقة الثالثة في دورة حياة النشاط، تُستدعى بعد onStart، والتي تشير إلى أن الشاشة جاهزة للتفاعل الكامل مع المستخدم. في هذه اللحظة، يكون النشاط في أعلى مكدس المهام، ويوجه النظام إليه جميع أحداث الإدخال، ويمكن للتطبيق بدء أي عمليات تتطلب مشاركة نشطة من المستخدم: مكالمات الفيديو، الألعاب، تسجيل الصوت، الرسم على Canvas.

onResume جزء من “العمر الأمامي” (foreground lifetime) — الفاصل الزمني بين onResume و onPause. هذه هي الفترة الأكثر نشاطاً للنشاط، حيث يستهلك التطبيق أكبر قدر من الموارد: وحدة المعالجة المركزية لمعالجة اللمس، وحدة معالجة الرسومات لعرض الرسوم المتحركة، الكاميرا والميكروفون لالتقاط الفيديو. فهم هذا المستوى من دورة الحياة أمر بالغ الأهمية لتحسين استهلاك الطاقة — الموارد التي تُفتح في onResume يجب أن تُغلق فوراً في onPause.

وفقاً لـ Google I/O 2025، متوسط الوقت الذي يقضيه النشاط في حالة onResume لكل جلسة هو 2–5 دقائق للتطبيقات الإخبارية و15–30 دقيقة للألعاب وتطبيقات المراسلة. كل الوقت الآخر، يكون النشاط في حالات onPause أو onStop أو onDestroy. هذا يعني أن تحسين كود onResume تحديداً يعطي أكبر مكاسب في الأداء وعمر البطارية.

onResume في النشاط

في النشاط، تُستدعى طريقة onResume في كل مرة تحصل فيها الشاشة على تركيز الإدخال — عند التشغيل الأول، عند العودة من نشاط آخر، عند إغلاق مربع حوار، عند فتح الجهاز. هذه طريقة “ساخنة” يمكن استدعاؤها عدة مرات في الجلسة، ويجب أن يكون تنفيذها خفيفاً قدر الإمكان.

kotlin
class CameraActivity : AppCompatActivity() {
    private var cameraProvider: ProcessCameraProvider? = null
    private var preview: Preview? = null

    override fun onResume() {
        super.onResume()
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            cameraProvider = cameraProviderFuture.get()
            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
            preview = Preview.Builder().build().also {
                it.setSurfaceProvider(binding?.viewFinder?.surfaceProvider)
            }
            try {
                cameraProvider?.unbindAll()
                cameraProvider?.bindToLifecycle(
                    this, cameraSelector, preview
                )
            } catch (e: Exception) {
                Log.e("Camera", "Failed to bind camera", e)
            }
        }, ContextCompact.getMainExecutor(this))
    }

    override fun onPause() {
        super.onPause()
        cameraProvider?.unbindAll()
        preview = null
    }
}

مثال CameraX يوضح الاستخدام الكلاسيكي لـ onResume/onPause: الكاميرا مورد حصري يمكن لتطبيق واحد فقط استخدامه في كل مرة. ربط الكاميرا بدورة الحياة عبر bindToLifecycle يغلق الكاميرا تلقائياً في onPause، لكن استدعاء unbindAll الصريح يضمن التحرير الفوري. هذا مهم بشكل خاص عند التبديل بين الأنشطة: يجب تحرير الكاميرا قبل أن يحاول نشاط آخر فتحها.

onResume في الجزء

onResume في الجزء يُستدعى بعد أن يحصل النشاط المحتوي عليه على onResume. ومع ذلك، نظراً لخصائص FragmentManager و ViewPager، قد يتأخر وقت استدعاء onResume للجزء بالنسبة للنشاط. على سبيل المثال، الجزء في ViewPager مع offscreenPageLimit = 1 يتلقى onResume فقط عندما يصبح الصفحة الحالية، وليس عند بدء النشاط.

kotlin
class VideoPlayerFragment : Fragment() {
    private var exoPlayer: ExoPlayer? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        exoPlayer = ExoPlayer.Builder(requireContext()).build()
        binding?.playerView?.player = exoPlayer
    }

    override fun onResume() {
        super.onResume()
        exoPlayer?.play()
        if (userVisibleHint) {
            startBiometricAuth()
        }
    }

    override fun onPause() {
        exoPlayer?.pause()
        stopBiometricAuth()
        super.onPause()
    }
}

فحص userVisibleHint في Fragment.onResume ذو صلة بـ ViewPager: قد يتلقى الجزء onResume لكن يكون مخفياً بصفحة مجاورة (على سبيل المثال، أثناء انتقال متحرك). في مثل هذه الحالات، بدء تشغيل الفيديو أو التحقق البيومتري في onResume دون التحقق من الرؤية سيؤدي إلى سلوك غير متوقع. ابتداءً من Fragment 1.5.0، يُوصى باستخدام FragmentTransaction.setMaxLifecycle() للتحكم الدقيق في دورة حياة الأجزاء في ViewPager2.

onResume مقابل onStart: متى نستخدم كل منهما

غالباً ما يخلط المطورون بين onStart و onResume، مما يضعون الكود في الطريقة الخطأ. القاعدة الرئيسية: onStart — للموارد التي تعمل أثناء الرؤية؛ onResume — للموارد التي تتطلب تركيز الإدخال. دعنا ننظر في سيناريوهات محددة والاختيار الصحيح للطريقة.

العمليةالطريقةالمبرر
الاشتراك في تحديد الموقعonStart / onStopGPS يمكن أن يعمل برؤية جزئية
فتح الكاميراonResume / onPauseالكاميرا مورد حصري
مستقبل البثonStart / onStopأحداث النظام لا تتطلب تركيزاً
تشغيل الفيديوonResume / onPauseيجب أن يكون الفيديو مرئياً للمستخدم
مسح BluetoothonStart / onStopالمسح يمكن أن يعمل في الخلفية
مسجل الصوت (MediaRecorder)onResume / onPauseالتسجيل يتطلب واجهة مستخدم نشطة
مستمعي الاستشعارonResume / onPauseأجهزة استشعار للألعاب والإيماءات
تحديث البياناتonStartبيانات حديثة مطلوبة عند الظهور

قاعدة عملية: إذا كانت العملية يجب أن تنقطع عند ظهور مربع حوار — استخدم onResume/onPause. إذا كانت العملية يمكن أن تستمر عندما تكون الشاشة مغطاة جزئياً — استخدم onStart/onStop. على سبيل المثال، مشغل الفيديو يجب أن يوقف الفيديو مؤقتاً عند فتح مربع حوار (onPause)، بينما تحديد الموقع يمكن أن يستمر في التحديث (يبقى في onStart).

إدارة الموارد الحصرية

الموارد الحصرية هي مكونات الجهاز التي يمكن استخدامها فقط من قبل تطبيق واحد في وقت معين. الكاميرا، الميكروفون، مخرج الفيديو (MediaProjection)، محول NFC في وضع القراءة، أجهزة USB في وضع الملحق — كل هذه الموارد يجب فتحها في onResume وتحريرها في onPause.

العمل مع MediaRecorder

يستخدم MediaRecorder لتسجيل الصوت والفيديو. يتم طلب الأذونات وإعداد MediaRecorder في onCreate، بينما يبدأ التسجيل في onResume. إذا انتقل المستخدم إلى تطبيق آخر، يوقف onPause التسجيل، ويستأنفه onResume. هذا هو السلوك القياسي لمسجلات الصوت وتطبيقات تسجيل الفيديو.

kotlin
private var mediaRecorder: MediaRecorder? = null
private var isRecording = false

override fun onResume() {
    super.onResume()
    if (isRecording) {
        mediaRecorder?.resume()
    }
}

override fun onPause() {
    if (isRecording) {
        mediaRecorder?.pause()
    }
    super.onPause()
}

BiometricPrompt و onResume

المصادقة البيومترية (BiometricPrompt) يجب استدعاؤها فقط عندما يكون النشاط في onResume. إذا تم استدعاؤها في onCreate أو onStart، قد يظهر مربع حوار البيومترية قبل أن يكمل النشاط التهيئة، مما يؤدي إلى معالجة غير صحيحة للنتيجة. استدعاؤها في onResume يضمن ظهور نافذة البيومترية في السياق الصحيح.

الأنماط والتوصيات

دعنا نلقي نظرة على ثلاثة أنماط مجربة للعمل مع onResume المستخدمة في المشاريع التجارية: إعادة تعيين مؤقت عدم النشاط، تحديث البيانات المرئية، والتكامل مع Jetpack Navigation.

إعادة تعيين مؤقت عدم النشاط

في التطبيقات ذات البيانات الحساسة (الخدمات المصرفية، السجلات الطبية)، يُستخدم onResume لإعادة تعيين مؤقت الخروج التلقائي. إذا كان المستخدم يتفاعل بنشاط مع التطبيق، يُستدعى onResume عند كل انتقال بين الشاشات، ويتم إعادة تعيين المؤقت. إذا صغر المستخدم التطبيق، يوقف onPause المؤقت، وعند العودة، يقوم onResume إما بإعادة تعيينه أو طلب مصادقة جديدة.

تحديث البيانات عند العودة

قائمة يجب أن تعرض بيانات محدثة في كل مرة يتم فيها العودة إلى الشاشة يتم تحديثها في onResume. على سبيل المثال، إذا قام المستخدم بإنشاء إدخال جديد في نشاط آخر وعاد للخلف، يقوم onResume بإعادة تحميل القائمة من قاعدة البيانات المحلية أو من ذاكرة التخزين المؤقت لـ ViewModel. هذا يضمن تناسق البيانات دون الحاجة إلى استدعاء notifyDataSetChanged يدوياً.

kotlin
override fun onResume() {
    super.onResume()
    // ActivityResultLauncher أعاد نتيجة — تحديث القائمة
    viewModel.refreshList()
    // إعادة تعيين مؤقت عدم النشاط
    inactivityTimer.reset()
}

Jetpack Navigation و onResume

في Jetpack Navigation، يُستدعى onResume للجزء في كل مرة تعود إليه عبر التنقل الخلفي. تُستخدم هذه الخاصية لإعادة تعيين حالة واجهة المستخدم: إخفاء لوحة المفاتيح، مسح حقول البحث، تحديث عنوان شريط الأدوات. OnBackPressedCallback مع onResume يعطي تحكماً كاملاً في التنقل دون تكرار الكود.

الأسئلة المتكررة

ما الفرق بين onResume و onStart بكلمات بسيطة؟

onStart — الشاشة مرئية. onResume — الشاشة نشطة وجاهزة للتفاعل. تخيل: أنت تشاهد التلفاز (onStart)، لكنك تلتقط جهاز التحكم عن بُعد (onResume). التلفاز مرئي دائماً، لكن التفاعل يبدأ فقط بجهاز التحكم. إذا قام شخص ما بتغطية التلفاز بستارة — تتوقف الشاشة عن الرؤية (onStop). إذا أخذ شخص منك جهاز التحكم — يتوقف التفاعل (onPause)، لكن التلفاز لا يزال مرئياً.

كم مرة يتم استدعاء onResume؟

يتم استدعاء onResume في كل مرة يحصل فيها النشاط على تركيز الإدخال. الحد الأدنى هو مرة واحدة (عند التشغيل). الحد الأقصى يعتمد على سيناريوهات الاستخدام: التبديل بين الشاشات، فتح مربعات الحوار، قفل وفتح الجهاز بسرعة — كل سيناريو من هذا القبيل يستدعي onResume عند العودة إلى الشاشة.

لماذا onResume هو أفضل مكان لفتح الكاميرا؟

الكاميرا مورد حصري متاح لتطبيق واحد فقط في كل مرة. إذا قمت بفتح الكاميرا في onCreate أو onStart، ستبقى مقفلة للتطبيقات الأخرى حتى عندما يكون تطبيقك غير نشط. يضمن onResume أن الكاميرا مفتوحة فقط عندما يكون النشاط في المقدمة، ويغلقها onPause فوراً. هذا هو المعيار في تطوير أندرويد، المثبت في وثائق CameraX و Camera2 API.

هل يمكن ألا يتم استدعاء onResume بعد onStart؟

نعم، قد لا يحدث onResume إذا تم تغطية النشاط بنشاط آخر مباشرة بعد الظهور. على سبيل المثال، النشاط A يبدأ النشاط B في طريقة onCreate أو onStart. في هذه الحالة، يتلقى A onStart → onPause → onStop، متجاوزاً onResume. النظام لا يستدعي onResume لأن النشاط A لم يحصل أبداً على تركيز الإدخال.

ما الذي لا يجب فعله في onResume؟

في onResume، لا يجب تنفيذ عمليات متزامنة طويلة: تحميل بيانات كبيرة من الشبكة، استعلامات SQL معقدة، معالجة الصور. onResume يعمل في سلسلة واجهة المستخدم، وأي حظر أطول من 100–200 مللي ثانية يؤدي إلى تأخير استجابة الواجهة. يجب أن تكون جميع العمليات الثقيلة غير متزامنة — عبر coroutines أو RxJava أو WorkManager. كما لا يُوصى باستدعاء finish() في onResume دون تحقق — فقد يؤدي ذلك إلى حلقة لا نهائية من إعادة الإنشاء.

الخلاصة

  • onResume — حالة المقدمة مع تركيز الإدخال؛ النشاط جاهز للتفاعل مع المستخدم
  • الموارد الحصرية — الكاميرا والميكروفون والتقاط الفيديو تُفتح في onResume وتُغلق في onPause
  • onResume مقابل onStart — onStart للموارد المرئية، onResume للموارد النشطة؛ مربع الحوار يقطع onResume لكن لا يقطع onStart
  • الأداء — يجب أن يكون onResume خفيفاً؛ جميع العمليات الثقيلة غير متزامنة
  • Fragment.onResume — يعتمد على الرؤية في ViewPager؛ تحقق من userVisibleHint أو استخدم setMaxLifecycle
  • المهام النموذجية — إعادة تعيين المؤقت، تحديث البيانات عند العودة، إدارة BiometricPrompt
  • زوج onResume/onPause — الموارد ذات الوصول الحصري تُدار حصرياً بواسطة هذا الزوج

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

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

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

اقرأ أيضًا