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 — یک متد 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 هنگام از دست دادن کامل دید Activity فراخوانی میشود، صرفنظر از علت: راهاندازی Activity جدید روی Activity فعلی، کوچکسازی برنامه (فشردن Home)، قفل صفحه، تماس ورودی یا باز شدن دیالوگ سیستمی. در همه این موارد Activity ابتدا onPause (از دست دادن نسبی فوکوس) و سپس onStop (از دست دادن کامل دید) را دریافت میکند.
سناریوهای اصلی فراخوانی onStop:
درک این نکته مهم است که onStop فراخوانی نمیشود هنگام چرخش صفحه — در این حالت Activity نابود میشود (onPause → onStop → onDestroy) و دوباره ایجاد میشود (onCreate → onStart → onResume). استثنا — پرچم android:configChanges="orientation" در مانیفست، که در آن Activity دوباره ایجاد نمیشود، بلکه فراخوانی onConfigurationChanged() را دریافت میکند.
onStop جایگاه مرکزی در توالی چرخه حیات Activity بین حالت قابل مشاهده و غیرقابل مشاهده دارد. توالی کامل: onCreate → onStart → onResume → (حالت فعال) → onPause → onStop → onDestroy (یا onRestart → onStart → onResume هنگام بازگشت).
| وضعیت | متد | قابلیت مشاهده | تعامل | حافظه |
|---|---|---|---|---|
| Created | onCreate | خیر | خیر | تخصیص داده میشود |
| Started | onStart | جزئی | خیر | کامل |
| Resumed | onResume | کامل | بله | کامل |
| Paused | onPause | جزئی | خیر | کامل |
| Stopped | onStop | خیر | خیر | کامل* |
| Destroyed | onDestroy | خیر | خیر | آزاد شده |
*در حالت Stopped Activity در حافظه نگهداری میشود، اما ممکن است توسط سیستم در صورت کمبود منابع کشته شود. اولویت کشته شدن فرآیندهای Stopped — ماقبل آخر، فقط بالاتر از فرآیندهای خالی کش شده.
onStop و onSaveInstanceState: سیستم onSaveInstanceState(Bundle) را قبل از onStop برای ذخیره وضعیت پویای UI فراخوانی میکند. توسعهدهنده این متد را برای ذخیره مقادیر فیلدهای ورودی، موقعیت RecyclerView، عناصر انتخاب شده در Bundle بازنویسی میکند. حتی اگر Activity نابود نشود (کاربر به سادگی آن را کوچک کرده و برگشته است)، Bundle هنگام تغییرات پیکربندی به onCreate منتقل میشود. Google توصیه میکند فقط وضعیت موقت UI را ذخیره کنید — نه دادههای مخزن یا ViewModel که خارج از Activity زندگی میکنند.
در onStop توسعهدهنده موظف است تمام منابعی را که وقتی Activity قابل مشاهده نیست مورد نیاز نیستند آزاد کند. این کار بار باتری، پردازنده و حافظه را کاهش میدهد و همچنین از ANR هنگام بازگشت به فعالیت جلوگیری میکند.
چه چیزی را در onStop آزاد کنیم:
در onStop چه کارهایی انجام ندهیم: عملیات طولانی انجام ندهید — ذخیره دادههای بزرگ در پایگاه داده، درخواستهای شبکه، محاسبات پیچیده. onStop در رشته اصلی اجرا میشود و بازگشت به Activity را مسدود میکند. برای عملیات طولانی از WorkManager با تأخیر یا کوروتینها در viewModelScope استفاده کنید. منابع ViewModel را آزاد نکنید — ViewModel از onStop جان سالم به در میبرد و هنگام بازگشت استفاده خواهد شد.
onPause و onStop از نظر درجه از دست دادن دید و حجم اقدامات اجباری متفاوت هستند. onPause هنگام از دست دادن نسبی فوکوس فراخوانی میشود (مثلاً باز شدن پنجره دیالوگ یا منوی سیستم)، onStop — هنگام از دست دادن کامل دید. این تفاوت برای انتخاب اینکه چه منابعی در هر مرحله آزاد شوند مهم است.
| ویژگی | onPause | onStop |
|---|---|---|
| درجه دید | تا حدودی قابل مشاهده | کاملاً غیرقابل مشاهده |
| فوکوس | از دست رفته | از دست رفته |
| زمان اجرا | تا 500 میلیثانیه | تا 5 ثانیه (مهلت ANR) |
| منابع برای آزادسازی | حیاتی (رسانه، دوربین) | همه غیرقابل مشاهده (سنسورها، انیمیشنها، location) |
| بازیابی | onResume | onRestart → onStart → onResume |
| اولویت فرآیند | بالا (Foreground) | متوسط (Background) |
قاعده کلی: در onPause منابع سیستمی را که بلافاصله بر تجربه کاربری برنامه دیگر تأثیر میگذارند (دوربین، پخشکننده رسانه) آزاد کنید، در onStop — تمام منابع دیگر که در Activity مخفی نیاز نیستند. Google توصیه میکند در onPause دادههای حیاتی کاربر (پیشنویس ایمیل، تنظیمات) را ذخیره کنید، زیرا onStop ممکن است در جابجایی سریع رخ ندهد.
هنگامی که کاربر به Activity مخفی بازمیگردد، سیستم onRestart → onStart → onResume را فراخوانی میکند. متد onRestart نشان میدهد که Activity از حالت Stopped بازمیگردد. این مرحله مهمی برای بازیابی UI و منابعی است که در onStop آزاد شده بودند.
توالی فراخوانیها هنگام بازگشت:
اگر فرآیند برنامه توسط سیستم در حالت Stopped کشته شده باشد، onCreate به جای onRestart فراخوانی میشود و Bundle از onSaveInstanceState برای بازیابی وضعیت منتقل میشود. این سناریو (process death) — یکی از رایجترین علل باگها در برنامههای اندروید است: توسعهدهندگان onRestart را پیادهسازی میکنند اما فراموش میکنند بازیابی از طریق onCreate پس از کشته شدن فرآیند را در نظر بگیرند.
خروج صحیح از سنسورها و توقف انیمیشن هنگام مخفی شدن Activity را نشان میدهد. پس از بازگشت به صفحه، منابع در onStart بازیابی میشوند.
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 منابع دوباره ایجاد میشوند.
رویکرد مدرن با استفاده از ViewModel + SavedStateHandle. دادههای فرم به طور خودکار در onStop بدون Bundle دستی ذخیره میشوند.
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 مستقیم توصیه میکند.
استفاده از lifecycleScope با کوروتینها برای ذخیره ناهمگام دادهها هنگام انتقال به onStop. کوروتین در dispatcher IO راهاندازی میشود و رشته اصلی را مسدود نمیکند.
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 — Activity دیگر قابل مشاهده نیست، اما در حافظه در حالت Stopped باقی میماند. سیستم میتواند Activity را از طریق onRestart بازگرداند. onDestroy — Activity نابود میشود، حافظه آزاد میشود. پس از onDestroy بازگشت فقط از طریق ایجاد نمونه جدیدی از Activity (onCreate) امکانپذیر است.
بله، اجباری است. super.onStop() عملکرد صحیح کامپوننتهای سیستمی را تضمین میکند: fragmentها، LoaderManager، ViewModelStore. حذف super.onStop() میتواند باعث نشت حافظه و بازیابی نادرست fragmentها شود. همیشه super.onStop() را آخر یا اول فراخوانی کنید — ترتیب حیاتی نیست، اما فراخوانی اجباری است.
از Log.d یا Timber در هر متد چرخه حیات استفاده کنید. فیلتر logcat را با برچسب Activity خود فعال کنید. برای تولید از Android Vitals استفاده کنید — Google به طور خودکار معیارهای چرخه حیات را جمعآوری کرده و ناهنجاریها را در Play Console نشان میدهد. همچنین مانیتورینگ چرخه حیات از طریق ProcessLifecycleOwner در دسترس است.
استثنای مدیریت نشده در onStop باعث Force Close برنامه میشود. سیستم استثناها را در callbackهای چرخه حیات مدیریت نمیکند. اگر در onStop عملیاتی انجام میشود که ممکن است استثنا پرتاب کند (کار با فایلها، شبکه)، آنها را در try-catch قرار دهید و خطا را ثبت کنید، بدون اینکه اجرای super.onStop() قطع شود.
خیر، Bitmap در Activity توسط GC جمعآوری میشود اگر به آن ارجاعی وجود نداشته باشد. آزادسازی اجباری (recycle()) در onStop لازم نیست و حتی مضر است — اگر Activity از طریق onRestart بازگردد، Bitmap باید دوباره بارگذاری شود. برای بارگذاری تصاویر از Glide یا Coil استفاده کنید — این کتابخانهها به طور خودکار حافظه نهان و چرخه حیات را مدیریت میکنند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید