onStart: الجوهر، ظهور Activity على شاشة Android

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

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

الرئيسية

  • onStart — يتم استدعاؤه عندما يصبح Activity أو Fragment مرئياً على الشاشة؛ يسبق onResume
  • تسجيل المستمعين — BroadcastReceiver، LocationListener، SensorListener يتم تسجيلهم في onStart وإلغاء تسجيلهم في onStop
  • الرسوم المتحركة — تشغيل الرسوم المتحركة التي يجب أن تعمل طالما الشاشة مرئية؛ الإيقاف المؤقت في onStop
  • الخدمات المرتبطة — الاتصال بالخدمات من نوع خادم-عميل عبر bindService في onStart، الفصل في onStop
  • onStart مقابل onResume — onStart = الرؤية، onResume = التركيز + التفاعل؛ مستويات مختلفة لنشاط الشاشة
  • Fragment.onStart — يتم استدعاؤه بعد Activity.onStart، عندما يصبح Fragment مرئياً في الحاوية
  • زوج onStart/onStop — الموارد المتصلة في onStart يجب تحريرها في onStop لمنع التسريبات

جوهر onStart في Android

onStart هي الطريقة الثانية في دورة حياة Activity، يتم استدعاؤها بواسطة النظام بعد onCreate (أو بعد onRestart عند العودة من حالة التوقف). في لحظة استدعاء onStart، يصبح Activity أو Fragment مرئياً على الشاشة. يرى المستخدم الواجهة، لكن الشاشة ليست جاهزة بعد للتفاعل — سيظهر تركيز الإدخال فقط بعد onResume.

طريقة onStart تدخل في «العمر المرئي» (visible lifetime) لـ Activity — الفاصل الزمني بين onStart و onStop. خلال هذه الفترة، قد يكون Activity مغطى جزئياً بنوافذ أخرى (مثل Activity شفاف أو نافذة حوار)، لكن واجهة UI الخاصة به تظل مرئية. هذا يميز العمر المرئي عن «العمر في المقدمة» (onResume — onPause)، عندما يكون لدى Activity تركيز إدخال كامل.

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

onStart في Activity

في Activity، يتم استدعاء onStart في كل مرة تظهر فيها الشاشة على العرض — سواء عند التشغيل الأول (بعد onCreate) أو عند العودة من الخلفية (بعد onRestart). على عكس onCreate، يمكن استدعاء onStart مرات متعددة خلال عمر مثيل Activity، لذلك يتم وضع الكود الذي يجب تنفيذه في كل مرة تظهر فيها الشاشة هنا.

kotlin
class DashboardActivity : AppCompatActivity() {
    private val connectivityReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val isConnected = ... // التحقق من ConnectivityManager
            binding?.statusIndicator?.setColor(
                if (isConnected) Color.GREEN else Color.RED
            )
        }
    }

    override fun onStart() {
        super.onStart()
        registerReceiver(
            connectivityReceiver,
            IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
        )
        SensorManager.getInstance().registerStepCounter()
    }

    override fun onStop() {
        unregisterReceiver(connectivityReceiver)
        SensorManager.getInstance().unregisterStepCounter()
        super.onStop()
    }
}

القاعدة الأساسية: جميع الموارد المتصلة في onStart يجب تحريرها في onStop. هذا يضمن أنه عندما يكون Activity مخفياً عن الشاشة، فإنه لا يستهلك البطارية، ولا يستمع لأحداث النظام، ولا يشغل الذاكرة. يحتوي Android Studio على قواعد lint تحذر من تسجيل BroadcastReceiver دون إلغاء تسجيل مماثل.

onStart في Fragment

onStart في Fragment مرتبط بشكل وثيق بدورة حياة Activity الحاوية. يتلقى Fragment استدعاء onStart بعد أن يتلقى Activity الذي يحتويه onStart. ومع ذلك، إذا تمت إضافة Fragment في وضع مؤجل (FragmentTransaction.commit() دون addToBackStack)، فقد يتم استدعاء onStart مع تأخير.

kotlin
class MapFragment : Fragment() {
    private var mapView: MapView? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        mapView = MapView(requireContext())
        return mapView!!
    }

    override fun onStart() {
        super.onStart()
        mapView?.onStart()
        LocationService.connect(requireContext())
    }

    override fun onStop() {
        mapView?.onStop()
        LocationService.disconnect()
        super.onStop()
    }
}

خصوصية Fragment.onStart: إذا كان Fragment في ViewPager مع offscreenPageLimit = 1، فإن الأجزاء المجاورة ستتلقى أيضاً onStart قبل أن تصبح مرئية. هذا قد يؤدي إلى تسجيل مبكر للمستمعين. لمثل هذه الحالات، استخدم طريقة setUserVisibleHint() أو تحقق من isVisible داخل onStart لتسجيل المستمعين فقط للأجزاء المرئية فعلياً.

الفرق بين onStart و onResume

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

يوضح جدول المقارنة بوضوح في أي السيناريوهات يتم استدعاء كل طريقة:

السيناريوonStartonResume
تشغيل التطبيقيتم استدعاؤهيتم استدعاؤه
Dialog مفتوح فوق Activityلا يتم استدعاؤهonPause (فقدان التركيز)
الضغط على زر الرئيسيةonStop (مخفي)onPause → onStop
العودة من الحديثةonStart (مرئي)onResume (تركيز)
تدوير الشاشةonCreate → onStart→ onResume
مكالمة واردةonStop (مخفي)onPause → onStop

هذا الجدول يساعد المطور في تحديد أي طريقة يضع فيها كوداً معيناً. على سبيل المثال، إذا كان التطبيق يجب أن يوقف تشغيل الفيديو عند أي تغطية للشاشة (حتى مع حوار)، يتم وضع الكود في onPause. إذا كان يجب أن يتوقف الفيديو فقط عند إخفاء الشاشة بالكامل — يتم وضع الكود في onStop.

تسجيل المستمعين والخدمات

onStart هو المكان الأمثل لتسجيل المستمعين الذين يجب أن يعملوا فقط عندما يكون Activity مرئياً على الشاشة. هذا يتعلق بثلاثة أنواع رئيسية من مكونات النظام: BroadcastReceiver لأحداث النظام، LocationListener لتحديد المواقع الجغرافية، و SensorListener لأجهزة الاستشعار.

BroadcastReceiver في onStart

BroadcastReceiver يتم تسجيله ديناميكياً عبر Context.registerReceiver() في onStart وإلغاء تسجيله في onStop عبر unregisterReceiver(). التسجيل الديناميكي أفضل من التسجيل الثابت (في البيان) لأنه يحد من عمر المستقبل بفترة رؤية Activity — التطبيق لا يستيقظ من رسائل البث النظامية عندما يكون Activity مخفياً.

kotlin
private val batteryReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent) {
        val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
        binding?.batteryText?.text = "$level%"
    }
}

override fun onStart() {
    super.onStart()
    registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
}

override fun onStop() {
    unregisterReceiver(batteryReceiver)
    super.onStop()
}

LocationListener و SensorListener

تحديد المواقع الجغرافية وأجهزة الاستشعار عمليات تستهلك موارد كثيرة. طلب تحديثات GPS في onStart والإلغاء في onStop يضمن أن التطبيق لا يستهلك البطارية عندما تكون الشاشة مخفية. للضبط الدقيق، استخدم requestLocationUpdates بفاصل زمني ومسافة أدنى — مثلاً 10 ثوان و 10 أمتار، مما يعطي توازناً مثالياً بين الدقة واستهلاك الطاقة.

الرسوم المتحركة و onStart

تشغيل الرسوم المتحركة في onStart، بدلاً من onCreate، يضمن أن الرسوم المتحركة تبدأ في كل مرة تظهر فيها الشاشة. إذا قمت بتشغيل رسم متحرك في onCreate، فسيعمل فقط عند إنشاء Activity لأول مرة، وليس عند العودة من الخلفية. يتم استدعاء onStart في كل مرة يصبح فيها Activity مرئياً، مما يجعله المكان المثالي لتشغيل الرسوم المتحركة الدورية والانتقالات.

kotlin
private lateinit var pulseAnimator: ValueAnimator

override fun onStart() {
    super.onStart()
    pulseAnimator.start()
    binding?.loadingIndicator?.animate()?.alpha(1f)?.start()
}

override fun onStop() {
    pulseAnimator.cancel()
    binding?.loadingIndicator?.animate()?.cancel()
    super.onStop()
}

للرسوم المتحركة التي تستخدم ObjectAnimator أو ValueAnimator، من المهم استدعاء cancel() في onStop. إذا استمر الرسم المتحرك في العمل بعد إخفاء Activity، فإنه يستهلك موارد GPU و CPU بدون فائدة، مما يقلل أداء الجهاز ويسرع استنزاف البطارية. يتيح Android Studio Profiler (رسم GPU) تتبع الرسوم المتحركة النشطة واكتشاف التسريبات.

قاعدة الزوج onStart/onStop تنطبق أيضاً على العمل مع الكاميرا للمعاينة (CameraX). فتح الكاميرا في onStart وإغلاقها في onStop يضمن أن الكاميرا غير محجوبة لتطبيقات أخرى عندما لا يكون تطبيقك مرئياً على الشاشة. انتهاك هذه القاعدة هو سبب شائع للمراجعات السلبية في Google Play.

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

ما الفرق بين onStart و onResume لتسجيل المستمعين؟

onStart — للمستمعين الذين يجب أن يعملوا طالما الشاشة مرئية (BroadcastReceiver، LocationListener، SensorListener). onResume — للموارد التي تتطلب وصولاً حصرياً (الكاميرا، التقاط الفيديو، التعرف على الكلام). مستمعو أحداث النظام لا يحتاجون وصولاً حصرياً ويمكنهم العمل مع تغطية جزئية — يتم تسجيلهم في onStart. يجب أن تكون الكاميرا نشطة فقط مع التركيز الكامل — يتم فتحها في onResume.

لماذا قد لا يتم استدعاء onStart؟

يتم استدعاء onStart دائماً إذا انتقل Activity إلى حالة مرئية. السيناريو الوحيد بدون onStart — يتم إنشاء Activity وإنهاؤه فوراً (مثلاً بسبب خطأ في onCreate). في هذه الحالة، يتم استدعاء onDestroy مباشرة بعد onCreate. لكن هذا سيناريو طارئ لا يجب أن يحدث في كود مكتوب بشكل صحيح.

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

نعم، قد لا يتلقى onStart onResume إذا تم فتح Activity آخر أو نافذة شفافة فوراً فوق Activity. على سبيل المثال، إذا تم تشغيل شاشة تفويض بعد onCreate (Activity A → Activity B)، في Activity A يتم استدعاء onStart، لكن onResume لا — يتلقى فوراً onPause → onStop عند التغطية بالشاشة B.

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

يمكن استدعاء onStart مرات متعددة خلال عمر مثيل Activity. في كل مرة ينتقل Activity من حالة مخفية (onStop) إلى حالة مرئية، يتم استدعاء onStart. عملياً، مع الاستخدام النشط للتطبيق، يمكن استدعاء onStart عشرات أو مئات المرات في الجلسة.

هل يجب تحميل البيانات في onStart؟

تحميل البيانات في onStart مبرر إذا كانت البيانات يجب أن تُحدَّث في كل مرة تظهر فيها الشاشة. مثلاً، قائمة الأخبار أو قائمة الإشعارات. لكن يجب أن يكون التحميل غير متزامن — عبر coroutines مع lifecycleScope، لتجنب حظر مسار UI. للبيانات التي لا تتغير بين ظهور الشاشة، يكفي تحميلها مرة واحدة في onCreate.

الخلاصة

  • onStart — طريقة العمر المرئي؛ يتم استدعاؤها عندما يظهر Activity أو Fragment على الشاشة
  • التسجيل في onStart — BroadcastReceiver، LocationListener، SensorListener يتم تسجيلهم في onStart وإلغاء تسجيلهم في onStop
  • onStart مقابل onResume — onStart = الرؤية، onResume = تركيز الإدخال؛ مستويات مختلفة لأنواع مختلفة من الموارد
  • الرسوم المتحركة — تشغيل الرسوم المتحركة الدورية في onStart، إيقافها في onStop؛ يمنع تسرب موارد GPU
  • Fragment.onStart — مرتبط بـ Activity.onStart؛ في ViewPager يتم استدعاؤه للأجزاء المجاورة مسبقاً
  • قاعدة الأزواج — جميع موارد onStart يجب تحريرها في onStop، وإلا تسرب للذاكرة والبطارية
  • تحميل البيانات — في onStart، يتم تحميل البيانات التي يجب تحديثها في كل مرة تظهر فيها الشاشة

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

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

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

اقرأ أيضًا