onStop — چیست، پنهان‌سازی Activity در چرخه حیات اندروید

نویسنده: IT Sectr منتشر شده: 2026-03-04 زمان مطالعه: 9 دقیقه

onStop — متد چرخه حیات Activity در اندروید است که توسط سیستم زمانی فراخوانی می‌شود که Activity دیگر برای کاربر قابل مشاهده نیست. Activity پس از اینکه Activity جدید آن را کاملاً بپوشاند یا هنگام کوچک‌سازی برنامه، به حالت Stopped منتقل می‌شود. در متد onStop توسعه‌دهنده موظف است انیمیشن‌ها را متوقف کند، منابع دوربین و سنسورها را آزاد کند، پیش‌نویس‌های داده‌های وارد شده را ذخیره کند. طبق Android Vitals (Google, 2025)، پردازش صحیح onStop تعداد ANR (Application Not Responding) را هنگام کوچک‌سازی برنامه به میزان 35% کاهش می‌دهد. پس از onStop سیستم می‌تواند onRestart (بازگشت به صفحه) یا onDestroy (پایان کامل) را فراخوانی کند. مستندات Android Developers درباره چرخه حیات Activity onStop را به عنوان مرز بین حالت قابل مشاهده و غیرقابل مشاهده توصیف می‌کند.

نکات اصلی

  • onStop — متدی که هنگام از دست دادن کامل دید Activity فراخوانی می‌شود، اما Activity همچنان در حافظه قرار دارد.
  • پس از onStop Activity به حالت Stopped می‌رود — در حافظه زنده است، اما قابل مشاهده نیست و با کاربر تعامل ندارد.
  • سیستم می‌تواند هنگام بازگشت به Activity، onRestart → onStart → onResume یا هنگام پایان، onDestroy را فراخوانی کند.
  • در onStop باید منابع را آزاد کرد: انیمیشن‌ها را متوقف کنید، سنسورها و دوربین را غیرفعال کنید، داده‌های موقت را ذخیره کنید.
  • پیاده‌سازی صحیح onStop — عامل کلیدی پایداری برنامه در چندوظیفگی و کوچک‌سازی است.

onStop در اندروید چیست؟

onStop — یک متد callback از کلاس AppCompatActivity (و سلف آن Activity) است که توسط سیستم عامل اندروید زمانی فراخوانی می‌شود که Activity کاملاً برای کاربر غیرقابل مشاهده می‌شود. در این لحظه Activity توسط Activity دیگر، پنجره دیالوگ، لانچر سیستم یا صفحه قفل پنهان شده است. از دیدگاه چرخه حیات، onStop پس از onPause می‌آید و نشان می‌دهد که Activity دیگر روی صفحه دیده نمی‌شود، اگرچه خود شیء Activity و وضعیت آن در حافظه باقی می‌مانند.

هنگامی که Activity به حالت Stopped (متوقف) می‌رود، وضعیت خود را در حافظه رم حفظ می‌کند — همه فیلدها، سلسله‌مراتب View و ViewModel قابل دسترس باقی می‌مانند. این Stopped را از حالت نابود شده (Destroyed) متمایز می‌کند، جایی که Activity کاملاً حذف می‌شود. System UI می‌تواند فرآیند برنامه‌ای را که در حالت Stopped است، در صورت کمبود حافظه بکشد — این به اصطلاح process death نامیده می‌شود. توسعه‌دهنده موظف است داده‌های حیاتی (پیش‌نویس‌ها، موقعیت اسکرول) را در onSaveInstanceState() ذخیره کند که قبل از onStop فراخوانی می‌شود تا بازیابی در هنگام کشته شدن فرآیند تضمین شود.

طبق مشخصات Android Compatibility Definition Document (CDD) برای نسخه 14+، فرآیند در حالت Stopped اولویت پایین‌تری برای کشته شدن توسط OOM Killer دارد — پایین‌تر از فرآیندهای در فاز Background، اما بالاتر از فرآیندهای کش شده. طبق آمار Google، 68% موارد کشته شدن فرآیندها زمانی رخ می‌دهد که Activity در حالت Stopped است، نه Paused.

چه زمانی onStop فراخوانی می‌شود: سناریوها و ترتیب

onStop هنگام از دست دادن کامل دید Activity فراخوانی می‌شود، صرف‌نظر از علت: راه‌اندازی Activity جدید روی Activity فعلی، کوچک‌سازی برنامه (فشردن Home)، قفل صفحه، تماس ورودی یا باز شدن دیالوگ سیستمی. در همه این موارد Activity ابتدا onPause (از دست دادن نسبی فوکوس) و سپس onStop (از دست دادن کامل دید) را دریافت می‌کند.

سناریوهای اصلی فراخوانی onStop:

  • راه‌اندازی Activity جدید روی Activity فعلی — Activity فعلی onPause و سپس onStop دریافت می‌کند؛ Activity جدید onCreate → onStart → onResume را طی می‌کند.
  • کوچک‌سازی برنامه (Home) — Activity در 200–300 میلی‌ثانیه به onPause → onStop می‌رود، در حافظه در حالت Stopped باقی می‌ماند.
  • قفل صفحه — سیستم onPause → onStop را فراخوانی می‌کند، زیرا صفحه قفل کاملاً Activity را می‌پوشاند.
  • تماس ورودی — Activity تلفن (Dialer) روی آن راه‌اندازی می‌شود، Activity فعلی به onStop می‌رود.
  • تغییر به برنامه دیگر (Recent Apps) — Activity پنهان می‌شود، onStop دریافت می‌کند، اما در کش فرآیندها باقی می‌ماند.

درک این نکته مهم است که onStop فراخوانی نمی‌شود هنگام چرخش صفحه — در این حالت Activity نابود می‌شود (onPause → onStop → onDestroy) و دوباره ایجاد می‌شود (onCreate → onStart → onResume). استثنا — پرچم android:configChanges="orientation" در مانیفست، که در آن Activity دوباره ایجاد نمی‌شود، بلکه فراخوانی onConfigurationChanged() را دریافت می‌کند.

onStop در چرخه حیات Activity

onStop جایگاه مرکزی در توالی چرخه حیات Activity بین حالت قابل مشاهده و غیرقابل مشاهده دارد. توالی کامل: onCreate → onStart → onResume → (حالت فعال) → onPause → onStop → onDestroy (یا onRestart → onStart → onResume هنگام بازگشت).

وضعیتمتدقابلیت مشاهدهتعاملحافظه
CreatedonCreateخیرخیرتخصیص داده می‌شود
StartedonStartجزئیخیرکامل
ResumedonResumeکاملبلهکامل
PausedonPauseجزئیخیرکامل
StoppedonStopخیرخیرکامل*
DestroyedonDestroyخیرخیرآزاد شده

*در حالت Stopped Activity در حافظه نگهداری می‌شود، اما ممکن است توسط سیستم در صورت کمبود منابع کشته شود. اولویت کشته شدن فرآیندهای Stopped — ماقبل آخر، فقط بالاتر از فرآیندهای خالی کش شده.

onStop و onSaveInstanceState: سیستم onSaveInstanceState(Bundle) را قبل از onStop برای ذخیره وضعیت پویای UI فراخوانی می‌کند. توسعه‌دهنده این متد را برای ذخیره مقادیر فیلدهای ورودی، موقعیت RecyclerView، عناصر انتخاب شده در Bundle بازنویسی می‌کند. حتی اگر Activity نابود نشود (کاربر به سادگی آن را کوچک کرده و برگشته است)، Bundle هنگام تغییرات پیکربندی به onCreate منتقل می‌شود. Google توصیه می‌کند فقط وضعیت موقت UI را ذخیره کنید — نه داده‌های مخزن یا ViewModel که خارج از Activity زندگی می‌کنند.

چه منابعی را در onStop آزاد کنیم

در onStop توسعه‌دهنده موظف است تمام منابعی را که وقتی Activity قابل مشاهده نیست مورد نیاز نیستند آزاد کند. این کار بار باتری، پردازنده و حافظه را کاهش می‌دهد و همچنین از ANR هنگام بازگشت به فعالیت جلوگیری می‌کند.

چه چیزی را در onStop آزاد کنیم:

  • انیمیشن‌ها و transitions — ObjectAnimator، ValueAnimator، ViewPropertyAnimator را متوقف کنید. انیمیشن در حال اجرای Activity غیرقابل مشاهده هدر دادن چرخه‌های GPU است.
  • سنسورها (Sensors) — از SensorManager خارج شوید (شتاب‌سنج، ژیروسکوپ، مغناطیس‌سنج). سنسورها حتی در Activity مخفی انرژی مصرف می‌کنند.
  • دوربین و میکروفون — Camera2 یا CameraX را آزاد کنید، MediaRecorder را متوقف کنید. فعال نگه داشتن دوربین در Activity مخفی توسط سیاست Google Play ممنوع است.
  • LocationListener — از FusedLocationProviderClient یا LocationManager خارج شوید. موقعیت جغرافیایی پرمصرف‌ترین منبع انرژی است.
  • Network listeners — WebSocket را ببندید، درخواست‌های HTTP که در پس‌زمینه نیاز نیستند را لغو کنید.
  • MediaPlayer و ExoPlayer — اگر پخش نباید در پس‌زمینه ادامه یابد، مکث یا متوقف کنید.

در onStop چه کارهایی انجام ندهیم: عملیات طولانی انجام ندهید — ذخیره داده‌های بزرگ در پایگاه داده، درخواست‌های شبکه، محاسبات پیچیده. onStop در رشته اصلی اجرا می‌شود و بازگشت به Activity را مسدود می‌کند. برای عملیات طولانی از WorkManager با تأخیر یا کوروتین‌ها در viewModelScope استفاده کنید. منابع ViewModel را آزاد نکنید — ViewModel از onStop جان سالم به در می‌برد و هنگام بازگشت استفاده خواهد شد.

تفاوت onStop و onPause

onPause و onStop از نظر درجه از دست دادن دید و حجم اقدامات اجباری متفاوت هستند. onPause هنگام از دست دادن نسبی فوکوس فراخوانی می‌شود (مثلاً باز شدن پنجره دیالوگ یا منوی سیستم)، onStop — هنگام از دست دادن کامل دید. این تفاوت برای انتخاب اینکه چه منابعی در هر مرحله آزاد شوند مهم است.

ویژگیonPauseonStop
درجه دیدتا حدودی قابل مشاهدهکاملاً غیرقابل مشاهده
فوکوساز دست رفتهاز دست رفته
زمان اجراتا 500 میلی‌ثانیهتا 5 ثانیه (مهلت ANR)
منابع برای آزادسازیحیاتی (رسانه، دوربین)همه غیرقابل مشاهده (سنسورها، انیمیشن‌ها، location)
بازیابیonResumeonRestart → onStart → onResume
اولویت فرآیندبالا (Foreground)متوسط (Background)

قاعده کلی: در onPause منابع سیستمی را که بلافاصله بر تجربه کاربری برنامه دیگر تأثیر می‌گذارند (دوربین، پخش‌کننده رسانه) آزاد کنید، در onStop — تمام منابع دیگر که در Activity مخفی نیاز نیستند. Google توصیه می‌کند در onPause داده‌های حیاتی کاربر (پیش‌نویس ایمیل، تنظیمات) را ذخیره کنید، زیرا onStop ممکن است در جابجایی سریع رخ ندهد.

onStop → onRestart: بازگشت به صفحه

هنگامی که کاربر به Activity مخفی بازمی‌گردد، سیستم onRestart → onStart → onResume را فراخوانی می‌کند. متد onRestart نشان می‌دهد که Activity از حالت Stopped بازمی‌گردد. این مرحله مهمی برای بازیابی UI و منابعی است که در onStop آزاد شده بودند.

توالی فراخوانی‌ها هنگام بازگشت:

  • onRestart() — Activity مطلع می‌شود که دوباره نمایش داده خواهد شد. اقدامات معمول: بارگذاری مجدد داده‌ها، به‌روزرسانی لیست‌ها.
  • onStart() — Activity قابل مشاهده می‌شود، اما هنوز فعال نیست. در اینجا منابع آزاد شده در onStop دوباره مقداردهی اولیه می‌شوند.
  • onResume() — Activity فوکوس دریافت می‌کند و آماده تعامل است. انیمیشن‌ها راه‌اندازی می‌شوند، سنسورها ثبت می‌شوند.

اگر فرآیند برنامه توسط سیستم در حالت Stopped کشته شده باشد، onCreate به جای onRestart فراخوانی می‌شود و Bundle از onSaveInstanceState برای بازیابی وضعیت منتقل می‌شود. این سناریو (process death) — یکی از رایج‌ترین علل باگ‌ها در برنامه‌های اندروید است: توسعه‌دهندگان onRestart را پیاده‌سازی می‌کنند اما فراموش می‌کنند بازیابی از طریق onCreate پس از کشته شدن فرآیند را در نظر بگیرند.

نمونه کدهای onStop در Kotlin

مثال 1: پیاده‌سازی پایه onStop با آزادسازی سنسورها

خروج صحیح از سنسورها و توقف انیمیشن هنگام مخفی شدن Activity را نشان می‌دهد. پس از بازگشت به صفحه، منابع در onStart بازیابی می‌شوند.

kotlin
class MainActivity : AppCompatActivity() {
    private lateinit var sensorManager: SensorManager
    private var accelerometer: Sensor? = null
    private var rotationAnimator: ObjectAnimator? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    }

    override fun onStart() {
        super.onStart()
        accelerometer?.let {
            sensorManager.registerListener(sensorListener, it, SensorManager.SENSOR_DELAY_NORMAL)
        }
        rotationAnimator = ObjectAnimator.ofFloat(findViewById(R.id.icon), "rotation", 0f, 360f)
        rotationAnimator?.apply {
            duration = 3000
            repeatMode = ValueAnimator.RESTART
            repeatCount = ValueAnimator.INFINITE
            start()
        }
    }

    override fun onStop() {
        super.onStop()
        sensorManager.unregisterListener(sensorListener)
        rotationAnimator?.cancel()
    }

    override fun onRestart() {
        super.onRestart()
        Log.d("MainActivity", "Activity از حالت Stopped بازمی‌گردد")
    }

    private val sensorListener = SensorEventListener { event, _ ->
        Log.d("MainActivity", "Accel: x=${event.values[0]}, y=${event.values[1]}, z=${event.values[2]}")
    }
}

کد سنسور شتاب‌سنج را ثبت می‌کند و یک انیمیشن چرخش نامحدود را در onStart راه‌اندازی می‌کند. در onStop سنسور غیرفعال و انیمیشن لغو می‌شود — این کار از مصرف باتری در Activity مخفی جلوگیری می‌کند. پس از بازگشت از طریق onRestart → onStart منابع دوباره ایجاد می‌شوند.

مثال 2: onStop با ذخیره وضعیت از طریق SavedStateHandle

رویکرد مدرن با استفاده از ViewModel + SavedStateHandle. داده‌های فرم به طور خودکار در onStop بدون Bundle دستی ذخیره می‌شوند.

kotlin
class FormViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    var email: String
        get() = savedStateHandle["email"] ?: ""
        set(value) { savedStateHandle["email"] = value }

    var message: String
        get() = savedStateHandle["message"] ?: ""
        set(value) { savedStateHandle["message"] = value }
}

class FormActivity : AppCompatActivity() {
    private val viewModel: FormViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_form)
        Log.d("FormActivity", "onCreate: email=${viewModel.email}")
    }

    override fun onStop() {
        super.onStop()
        Log.d("FormActivity", "onStop: داده‌ها در SavedStateHandle ذخیره شدند")
    }
}

SavedStateHandle به طور خودکار مقادیر را در Bundle هنگام onSaveInstanceState ذخیره می‌کند که قبل از onStop فراخوانی می‌شود. هنگام چرخش صفحه یا کشته شدن فرآیند، داده‌ها بدون از دست رفتن بازیابی می‌شوند. Google SavedStateHandle را برای فرم‌ها و پیش‌نویس‌ها به جای onSaveInstanceState مستقیم توصیه می‌کند.

مثال 3: lifecycleScope برای عملیات در onStop

استفاده از lifecycleScope با کوروتین‌ها برای ذخیره ناهمگام داده‌ها هنگام انتقال به onStop. کوروتین در dispatcher IO راه‌اندازی می‌شود و رشته اصلی را مسدود نمی‌کند.

kotlin
class NoteActivity : AppCompatActivity() {
    private val noteRepository = NoteRepository()

    override fun onStop() {
        lifecycleScope.launch(Dispatchers.IO) {
            val text = findViewById<EditText>(R.id.note_content).text.toString()
            noteRepository.saveDraft(text)
            withContext(Dispatchers.Main) {
                Log.d("NoteActivity", "پیش‌نویس در onStop ذخیره شد")
            }
        }
        super.onStop()
    }
}

کوروتین lifecycleScope.launch اگر چرخه حیات Activity پایان یابد به طور خودکار لغو می‌شود. استفاده از Dispatchers.IO تضمین می‌کند که نوشتن در پایگاه داده یا فایل، بازگشت به Activity را مسدود نمی‌کند. طبق Google، کوروتین‌ها در lifecycleScope روش ترجیحی برای عملیات ناهمگام در onStop هستند.

سوالات متداول

تفاوت onStop و onDestroy چیست؟

onStop — Activity دیگر قابل مشاهده نیست، اما در حافظه در حالت Stopped باقی می‌ماند. سیستم می‌تواند Activity را از طریق onRestart بازگرداند. onDestroy — Activity نابود می‌شود، حافظه آزاد می‌شود. پس از onDestroy بازگشت فقط از طریق ایجاد نمونه جدیدی از Activity (onCreate) امکان‌پذیر است.

آیا فراخوانی super.onStop() اجباری است؟

بله، اجباری است. super.onStop() عملکرد صحیح کامپوننت‌های سیستمی را تضمین می‌کند: fragment‌ها، LoaderManager، ViewModelStore. حذف super.onStop() می‌تواند باعث نشت حافظه و بازیابی نادرست fragment‌ها شود. همیشه super.onStop() را آخر یا اول فراخوانی کنید — ترتیب حیاتی نیست، اما فراخوانی اجباری است.

چگونه بررسی کنیم که onStop فراخوانی شده است؟

از Log.d یا Timber در هر متد چرخه حیات استفاده کنید. فیلتر logcat را با برچسب Activity خود فعال کنید. برای تولید از Android Vitals استفاده کنید — Google به طور خودکار معیارهای چرخه حیات را جمع‌آوری کرده و ناهنجاری‌ها را در Play Console نشان می‌دهد. همچنین مانیتورینگ چرخه حیات از طریق ProcessLifecycleOwner در دسترس است.

اگر در onStop استثنا پرتاب شود چه اتفاقی می‌افتد؟

استثنای مدیریت نشده در onStop باعث Force Close برنامه می‌شود. سیستم استثناها را در callbackهای چرخه حیات مدیریت نمی‌کند. اگر در onStop عملیاتی انجام می‌شود که ممکن است استثنا پرتاب کند (کار با فایل‌ها، شبکه)، آنها را در try-catch قرار دهید و خطا را ثبت کنید، بدون اینکه اجرای super.onStop() قطع شود.

آیا لازم است Bitmap در onStop آزاد شود؟

خیر، Bitmap در Activity توسط GC جمع‌آوری می‌شود اگر به آن ارجاعی وجود نداشته باشد. آزادسازی اجباری (recycle()) در onStop لازم نیست و حتی مضر است — اگر Activity از طریق onRestart بازگردد، Bitmap باید دوباره بارگذاری شود. برای بارگذاری تصاویر از Glide یا Coil استفاده کنید — این کتابخانه‌ها به طور خودکار حافظه نهان و چرخه حیات را مدیریت می‌کنند.

خلاصه

  • onStop — متد چرخه حیات Activity که هنگام از دست دادن کامل دید فراخوانی می‌شود. Activity در حافظه در حالت Stopped باقی می‌ماند.
  • پس از onStop دو سناریو ممکن است: onRestart (بازگشت به صفحه) یا onDestroy (نابودی Activity).
  • در onStop باید سنسورها، انیمیشن‌ها، دوربین، location-listenerها را آزاد کنید — همه چیزهایی که در Activity غیرقابل مشاهده نیاز نیستند.
  • onStop با onPause از نظر درجه دید متفاوت است: onPause — از دست دادن نسبی، onStop — از دست دادن کامل دید.
  • onSaveInstanceState قبل از onStop فراخوانی می‌شود — از آن برای ذخیره وضعیت موقت UI استفاده کنید.
  • کوروتین‌های lifecycleScope با Dispatchers.IO — روش ترجیحی برای عملیات ناهمگام در onStop.
  • همیشه super.onStop() را فراخوانی کنید و عملیات خطرناک را برای جلوگیری از Force Close در try-catch قرار دهید.

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

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

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

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