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
  • سرویس‌های Bound — اتصال به سرویس‌های مشتری-سرور از طریق 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 محدود می‌کند — برنامه از پیام‌های broadcast سیستمی بیدار نمی‌شود وقتی 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 با حداقل فاصله زمانی و مسافت استفاده می‌شود — مثلاً ۱۰ ثانیه و ۱۰ متر، که تعادل بهینه بین دقت و مصرف انرژی را فراهم می‌کند.

انیمیشن‌ها و 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). در این حالت بعد از onCreate بلافاصله onDestroy فراخوانی می‌شود. اما این یک سناریوی اضطراری است که نباید در کد درست نوشته شده وجود داشته باشد.

آیا onStart می‌تواند بدون onResume فراخوانی شود؟

بله، onStart ممکن است onResume را دریافت نکند اگر بلافاصله روی Activity دیگری یا پنجره شفاف باز شود. مثلاً، اگر بعد از onCreate صفحه احراز هویت راه‌اندازی شود (Activity A → Activity B)، در Activity A onStart فراخوانی می‌شود، اما onResume نه — بلافاصله هنگام پوشیده شدن با صفحه B onPause → onStop دریافت می‌کند.

چند بار می‌توان onStart فراخوانی شد؟

onStart می‌تواند چندین بار در طول عمر یک نمونه Activity فراخوانی شود. هر بار که Activity از حالت مخفی (onStop) به حالت قابل مشاهده می‌رود، onStart فراخوانی می‌شود. در عمل، با استفاده فعال از برنامه، onStart ممکن است ده‌ها یا صدها بار در یک جلسه فراخوانی شود.

آیا بارگذاری داده‌ها در onStart ارزش دارد؟

بارگذاری داده‌ها در onStart اگر داده‌ها باید هر بار هنگام ظاهر شدن صفحه به‌روز شوند، توجیه‌پذیر است. مثلاً، فید خبری یا لیست اعلان‌ها. اما بارگذاری باید ناهمگام باشد — از طریق کوروتین‌ها با lifecycleScope، تا thread UI مسدود نشود. برای داده‌هایی که بین ظهورهای صفحه تغییر نمی‌کنند، بارگذاری یکبار در onCreate کافی است.

خلاصه

  • onStart — متد عمر قابل مشاهده؛ وقتی Activity یا Fragment روی صفحه ظاهر می‌شوند فراخوانی می‌شود
  • ثبت در onStart — BroadcastReceiver، LocationListener، SensorListener در onStart ثبت و در onStop لغو ثبت می‌شوند
  • onStart vs onResume — onStart = قابلیت مشاهده، onResume = فوکوس ورودی؛ سطوح مختلف برای انواع مختلف منابع
  • انیمیشن‌ها — شروع انیمیشن‌های چرخه‌ای در onStart، توقف در onStop؛ جلوگیری از نشت منابع GPU
  • Fragment.onStart — وابسته به Activity.onStart؛ در ViewPager برای فرگمنت‌های مجاور زودتر فراخوانی می‌شود
  • قانون جفت — همه منابع onStart باید در onStop آزاد شوند، در غیر این صورت نشت حافظه و باتری
  • بارگذاری داده — در onStart داده‌هایی بارگذاری می‌شوند که باید در هر ظهور صفحه به‌روز شوند

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید