Activity Lifecycle — مجموعهای از متدهای بازگشتی است که Android هنگام انتقال Activity بین حالتها فراخوانی میکند: ایجاد، نمایانی، فوکوس ورودی، از دست دادن جزئی نمایانی، پنهان شدن کامل و نابودی. سیستم چرخه حیات هر صفحه برنامه را از لحظه فراخوانی onCreate() تا onDestroy مدیریت میکند. درک این حالتها یک نیاز الزامی برای عملکرد پایدار برنامه Android است، زیرا پردازش نادرست انتقال بین متدها منجر به نشت حافظه، از دست رفتن دادههای کاربر و کرشهای غیرمنتظره میشود. درباره معماری Android بیشتر در مقاله کلی درباره Android بخوانید.
نکات اصلی
Activity Lifecycle (چرخه حیات Activity) — یک ماشین حالت نهایی است که هر صفحه برنامه Android از لحظه ایجاد تا نابودی کامل از آن عبور میکند. سیستم Android این فرآیند را بر اساس اقدامات کاربر مدیریت میکند: باز کردن برنامه، کوچک کردن، چرخش صفحه، پاسخ به تماس ورودی، جابجایی بین برنامهها و پایان کار.
درک چرخه حیات برای هر توسعهدهنده Android ضروری است، زیرا سیستم میتواند در هر لحظه Activity را در صورت کمبود حافظه نابود کند — و برنامه موظف است حالت خود را به درستی بازیابی کند. طبق دادههای Google Android Vitals (2025)، برنامههایی که ذخیره حالت در onSaveInstanceState() را پردازش نمیکنند، در هنگام بازآفرینی Activity 42٪ کرش بیشتری نشان میدهند.
چرخه حیات شامل شش متد بازگشتی اصلی است: onCreate()، onStart()، onResume()، onPause()، onStop()، onDestroy(). علاوه بر این، متد onRestart() وجود دارد که قبل از onStart() زمانی که Activity از حالت متوقف بازمیگردد فراخوانی میشود. هر متد هدف و زمان اجرای کاملاً مشخصی دارد — سیستم آنها را به ترتیب فراخوانی میکند و توسعهدهنده میتواند هر یک را برای اجرای منطق خود بازنویسی کند.
چرخه را میتوان به سه مرحله کلیدی تقسیم کرد: کل طول عمر (onCreate → onDestroy)، طول عمر قابل مشاهده (onStart → onStop) و طول عمر در پیشزمینه (onResume → onPause). درک این سه سطح به توزیع صحیح کد مقداردهی اولیه و آزادسازی منابع کمک میکند.
هر متد چرخه حیات یک وظیفه کاملاً مشخص را انجام میدهد. سیستم آنها را به ترتیب ثابت فراخوانی میکند و توسعهدهنده باید فقط متدهایی را که برای منطق خاص نیاز است بازنویسی کند. توصیه نمیشود مستقیماً متدهای چرخه حیات را فراخوانی کنید — این کار توسط Android Runtime انجام میشود.
دنباله معمولی هنگام راهاندازی برنامه: onCreate → onStart → onResume. هنگام فشار دکمه «بازگشت»: onPause → onStop → onDestroy. هنگام کوچک کردن: onPause → onStop، سپس هنگام بازگشت: onRestart → onStart → onResume.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onStop() {
super.onStop()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onRestart() {
super.onRestart()
}
}
هر متد بازنویسی شده موظف است نسخه super را فراخوانی کند — بدون این کار سیستم نمیتواند انتقال بین حالتها را به درستی کامل کند. این قانون در مستندات Android Developers ثبت شده و توسط قوانین lint Android Studio بررسی میشود.
سطح اول — کل طول عمر (entire lifetime): فاصله بین onCreate و onDestroy. در اینجا مقداردهی اولیه یکباره و آزادسازی نهایی منابع جهانی انجام میشود. سطح دوم — طول عمر قابل مشاهده (visible lifetime): بین onStart و onStop. Activity روی صفحه قابل مشاهده است، اما ممکن است تا حدی توسط پنجره دیگری پوشانده شود. سطح سوم — طول عمر در پیشزمینه (foreground lifetime): بین onResume و onPause. Activity در بالای پشته وظایف قرار دارد و با کاربر تعامل میکند.
onCreate() — اولین و تنها متد اجباری چرخه حیات Activity. این متد یک بار توسط سیستم هنگام ایجاد نمونه Activity فراخوانی میشود. این متد پارامتر savedInstanceState: Bundle? را دریافت میکند که شامل حالت ذخیرهشده قبلی است، اگر Activity پس از نابودی دوباره ایجاد شود — مثلاً هنگام چرخش صفحه.
داخل onCreate وظایف زیر انجام میشود: مقداردهی اولیه رابط کاربری از طریق setContentView() با ارسال منبع layout، اتصال عناصر View از طریق findViewById()، تنظیم آداپتورها برای RecyclerView و ViewPager، بازیابی حالت از savedInstanceState، مقداردهی اولیه ViewModel و LiveData، تنظیم شنوندگان کلیک و حرکات. متد باید در سریعترین زمان ممکن پایان یابد — عملیات طولانی در اینجا رندر اولین فریم را مسدود میکند که زمان راهاندازی برنامه را افزایش میدهد.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile)
val userNameText: TextView = findViewById(R.id.user_name)
val loadButton: Button = findViewById(R.id.load_button)
if (savedInstanceState != null) {
userNameText.text = savedInstanceState.getString("user_name")
}
loadButton.setOnClickListener {
loadUserProfile()
}
}
اگر Activity برای اولین بار ایجاد میشود، savedInstanceState برابر null است. هنگام بازآفرینی پس از چرخش صفحه، Bundle شامل دادههایی است که در onSaveInstanceState() ذخیره شدهاند. بررسی null — یک روش استاندارد برای بازیابی صحیح UI بدون از دست دادن دادههای وارد شده توسط کاربر.
onStart() بلافاصله پس از onCreate() یا پس از onRestart() فراخوانی میشود، زمانی که Activity برای کاربر قابل مشاهده میشود. در این حالت Activity هنوز در پیشزمینه قرار ندارد و نمیتواند با کاربر تعامل کند، اما رابط کاربری آن روی صفحه قابل مشاهده است. مثلاً هنگام راهاندازی برنامه بین فراخوانی onStart و onResume، سیستم اولین فریم رابط را رندر میکند.
در متد onStart معمولاً اقدامات زیر انجام میشود: شروع انیمیشنهایی که باید تا زمانی که Activity قابل مشاهده است کار کنند؛ اتصال گیرندههای پخش (BroadcastReceiver)؛ اتصال به سرویسهای موقعیتیابی و سنسورها؛ بهروزرسانی دادهها از ViewModel یا Room. همچنین در اینجا اتصال به Bound-سرویسها از طریق bindService() انجام میشود، اگر برنامه از معماری مشتری-سرور درون فرآیندی استفاده کند.
override fun onStart() {
super.onStart()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
5000L,
10f,
locationListener
)
}
override fun onStop() {
super.onStop()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.removeUpdates(locationListener)
}
قانون مهم: منابعی که در onStart متصل شدهاند، باید در onStop آزاد شوند. این تضمین میکند که وقتی Activity روی صفحه قابل مشاهده نیست، باتری و منابع سیستم را مصرف نمیکند. Google Play Store برنامهها را برای نشت LocationListener و سایر سرویسهای سیستمی هنگام تأیید بهروزرسانیها بررسی میکند.
onResume() — حالتی که در آن Activity در پیشزمینه قرار دارد و آماده تعامل با کاربر است. این حالت کاری صفحه است: سیستم فوکوس ورودی را به Activity میدهد و تمام رویدادهای لمسی، ورودی صفحهکلید و حرکات به این صفحه هدایت میشوند. متد onResume هر بار که Activity به پیشزمینه بازمیگردد فراخوانی میشود — پس از پایان Activity دیگر، پس از بسته شدن پنجره دیالوگ، پس از باز کردن قفل دستگاه.
در onResume انجام میشود: از سرگیری انیمیشنهایی که در onPause متوقف شده بودند؛ باز کردن دوربین و سایر منابع انحصاری؛ ثبت شنوندگان سنسور (شتابسنج، ژیروسکوپ)؛ شروع تایمرها و کرونومتر برای UI؛ بهروزرسانی محتوای صفحه با دادههای بهروز. در جفت onResume / onPause با منابعی کار میشود که فقط هنگام فوکوس باید فعال باشند — مثلاً تشخیص گفتار پیوسته یا ضبط ویدئو.
override fun onResume() {
super.onResume()
cameraHolder.openCamera()
animator.resume()
sensorManager.registerListener(
stepCounter,
sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
SensorManager.SENSOR_DELAY_NORMAL
)
}
override fun onPause() {
super.onPause()
cameraHolder.closeCamera()
animator.pause()
sensorManager.unregisterListener(stepCounter)
}
تفاوت بین onStart و onResume قابل توجه است: Activity ممکن است قابل مشاهده باشد (onStart)، اما فعال نباشد (onResume) — مثلاً وقتی یک پنجره دیالوگ شناور یا صفحه قفل شفاف روی آن نمایش داده میشود. دقیقاً در onResume، نه در onStart، باید منابع انحصاری را که نیاز به دسترسی انحصاری دارند باز کرد.
onPause() زمانی فراخوانی میشود که Activity فوکوس ورودی را از دست میدهد، اما همچنان تا حدی قابل مشاهده است. سناریوهای معمول: باز شدن پنجره دیالوگ، فشار دکمه «برنامههای اخیر»، تماس ورودی، فشار دکمه «خانه» (در این حالت پس از onPause، onStop فراخوانی میشود). متد onPause — آخرین مکان مطمئن برای ذخیره دادههایی است که کاربر نباید از دست بدهد.
در onPause انجام میشود: ذخیره پیشنویسهای ایمیل و فرمهای ورودی در Room یا SharedPreferences؛ توقف انیمیشنها و پخش ویدئو؛ بستن دوربین و آزادسازی منابع انحصاری؛ لغو عملیات پرهزینه که برای پسزمینه حیاتی نیستند. متد onPause باید در کمتر از ۱۰۰ میلیثانیه پایان یابد — سیستم انتقال به Activity بعدی را مسدود میکند تا زمانی که onPause کنترل را بازگرداند و تجاوز از حد مجاز منجر به ANR (Application Not Responding) میشود.
override fun onPause() {
super.onPause()
val editor = SharedPreferences.Manager ...
editor.putString("draft_text", draftEditText.text.toString())
editor.apply()
videoView.pause()
cameraHolder.release()
}
مهم: onPause در UI-رشته اجرا میشود، بنابراین هر عملیات مسدودکننده، مانند نوشتن در پایگاه داده از طریق Room با درخواست همزمان، باید با ناهمزمان (کوروتین) جایگزین شود یا در رشته پسزمینه انجام شود. از apply() به جای commit() برای SharedPreferences استفاده کنید — apply دادهها را به صورت ناهمزمان مینویسد و UI-رشته را مسدود نمیکند.
onStop() زمانی فراخوانی میشود که Activity دیگر برای کاربر قابل مشاهده نیست. این در موارد زیر رخ میدهد: Activity کاملاً توسط Activity دیگر پوشانده شده است؛ کاربر دکمه «خانه» را فشار داده یا به برنامه دیگری رفته است؛ Activity در حال پایان است (سپس onDestroy فراخوانی میشود). در حالت onStop، Activity در حافظه باقی میماند و تمام فیلدهای خود را حفظ میکند — نابود نشده، اما فعال هم نیست.
در onStop انجام میشود: لغو اشتراک از BroadcastReceiver که در onStart ثبت شده بودند؛ قطع اتصال از Bound-سرویسها؛ آزادسازی LocationListener، SensorListener و سایر شنوندگان سیستمی؛ توقف عملیات طولانی پسزمینه که وقتی برنامه پنهان است نیازی نیست؛ نوشتن حالت فعلی UI در Bundle از طریق onSaveInstanceState()، اگر این کار در onPause انجام نشده بود.
override fun onStop() {
super.onStop()
unregisterReceiver(connectivityReceiver)
unbindService(serviceConnection)
if (isChangingConfigurations()) {
Log.d("Lifecycle", "Activity به دلیل تغییر پیکربندی دوباره ایجاد میشود")
}
}
سیستم میتواند Activity را در حالت onStop بدون فراخوانی onDestroy در صورت کمبود حافظه نابود کند. بنابراین تمام دادههای حیاتی باید قبل از انتقال به onStop ذخیره شوند. پرچم isChangingConfigurations() امکان تشخیص ارتباط فراخوانی onStop با چرخش صفحه را میدهد — در این صورت Activity دوباره ایجاد میشود، نه اینکه پایان یابد.
onDestroy() — آخرین متد چرخه حیات که قبل از نابودی کامل Activity فراخوانی میشود. سیستم onDestroy را در دو حالت فراخوانی میکند: Activity با فراخوانی finish() پایان مییابد یا کاربر دکمه «بازگشت» را فشار میدهد؛ Activity توسط سیستم به دلیل تغییر پیکربندی (مثلاً چرخش صفحه) نابود میشود و دوباره ایجاد خواهد شد. متد onDestroy امکان پاکسازی نهایی منابع را فراهم میکند: قطع اتصال رشتهها و کوروتینها، بستن کرسرها و سوکتهای دائماً باز، آزادسازی حافظه بومی از طریق NDK.
override fun onDestroy() {
super.onDestroy()
backgroundJob.cancel()
dbHelper.close()
if (isFinishing) {
Log.d("Lifecycle", "Activity به طور کامل پایان مییابد")
} else {
Log.d("Lifecycle", "Activity دوباره ایجاد خواهد شد")
}
}
نکته مهم: onDestroy تضمین نمیشود اگر فرآیند برنامه توسط سیستم کشته شود (out-of-memory kill). بنابراین نمیتوان برای ذخیره دادهها به onDestroy تکیه کرد — این وظیفه در onPause یا onStop حل میشود. ویژگی isFinishing امکان تشخیص پایان Activity توسط finish() از بازآفرینی در تغییر پیکربندی را میدهد.
onRestart() قبل از onStart() فراخوانی میشود، زمانی که Activity از حالت متوقف (onStop) به پیشزمینه بازمیگردد. این زمانی رخ میدهد که کاربر برنامه را از منوی «اخیر» دوباره باز میکند یا با فشار دکمه «بازگشت» در صفحه فرزند به Activity بازمیگردد. متد onRestart امکان اجرای منطق متفاوت از onCreate را میدهد — مثلاً بهروزرسانی دادههایی که ممکن است در زمانی که Activity پنهان بود تغییر کرده باشند.
override fun onRestart() {
super.onRestart()
refreshDataFromNetwork()
Log.d("Lifecycle", "Activity از پشته راهاندازی مجدد میشود")
}
سناریوی معمول: کاربر برنامه را باز کرد، به وظیفه دیگری سوئیچ کرد و یک ساعت بعد بازگشت. در onRestart برنامه میتواند بهروزرسانی دادهها را بررسی کند و اگر زمان زیادی گذشته باشد، پیشنهاد بارگذاری مجدد محتوا را بدهد. این تجربه کاربری را بهبود میبخشد و احتمال نمایش اطلاعات قدیمی را کاهش میدهد.
چرخش صفحه — رایجترین سناریوی بازآفرینی Activity. به طور پیشفرض، Android Activity فعلی را نابود کرده و یک Activity جدید در هر تغییر جهت ایجاد میکند. اگر حالت ذخیره نشود، کاربر تمام دادههای وارد شده را از دست میدهد. برای این منظور Android دو مکانیزم ارائه میدهد: onSaveInstanceState() برای دادههای قابل سریالسازی و ViewModel برای دادههایی که از تغییرات پیکربندی جان سالم به در میبرند.
onSaveInstanceState() قبل از نابودی Activity برای ذخیره حالت موقت فراخوانی میشود. دادههای ذخیره شده در onCreate از طریق پارامتر savedInstanceState و در متد onRestoreInstanceState() که پس از onStart فراخوانی میشود منتقل میگردند. Bundle محدودیت اندازه دارد — حدود ۵۰۰ کیلوبایت، بنابراین حجمهای بزرگ داده (مثلاً بیتمپها) از طریق ViewModel ذخیره میشوند.
<!-- AndroidManifest.xml — ثابت کردن جهت -->
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
ثابت کردن جهت از طریق android:configChanges از بازآفرینی Activity جلوگیری میکند، اما یک ضدالگو محسوب میشود اگر برنامه باید از هر دو جهت پشتیبانی کند. توصیه مدرن Google — استفاده از ViewModel در کنار onSaveInstanceState برای دادههایی که کاربر در UI وارد میکند.
Fragment چرخه حیات مخصوص به خود را دارد، مشابه Activity، اما با متدهای اضافی: onAttach، onCreate، onCreateView، onViewCreated، onStart، onResume، onPause، onStop، onDestroyView، onDestroy، onDetach. Fragment همیشه داخل Activity وجود دارد و چرخه حیات آن به چرخه حیات Activity-میزبان وابسته است. اگر Activity نابود شود، Fragment نیز از آن پیروی میکند.
تفاوت اصلی: Fragment نه تنها حالت مؤلفه، بلکه سلسله مراتب View را نیز مدیریت میکند. متد onCreateView View ریشه Fragment را برمیگرداند و onDestroyView این سلسله مراتب را نابود میکند. این به Fragment اجازه میدهد تا از بازآفرینی Activity در هنگام چرخش صفحه جان سالم به در ببرد: Fragment حفظ میشود، اما View آن در onCreateView دوباره ایجاد میشود.
class ProfileFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_profile, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val avatarImage: ImageView = view.findViewById(R.id.avatar_image)
loadAvatar(avatarImage)
}
}
درک تفاوت بین onCreate و onCreateView بسیار مهم است: onCreate یک بار در طول عمر Fragment فراخوانی میشود (حتی هنگام بازآفرینی View)، در حالی که onCreateView هر بار که Fragment سلسله مراتب View خود را ایجاد یا بازآفرینی میکند فراخوانی میشود. مقداردهی اولیه دادهها در onCreate انجام میشود و اتصال UI در onViewCreated.
LifecycleObserver — مؤلفه کتابخانه Android Jetpack که امکان واکنش به تغییرات چرخه حیات را بدون بازنویسی متدها در Activity یا Fragment فراهم میکند. به جای تکرار کد در هر متد چرخه حیات، توسعهدهنده یک کلاس جداگانه با حاشیهنویسیهای @OnLifecycleEvent ایجاد کرده و آن را به lifecycle.addObserver() منتقل میکند.
Jetpack همچنین کلاس LifecycleOwner را ارائه میدهد — یک رابط که AppCompatActivity و Fragment آن را پیادهسازی میکنند. هر شیء که LifecycleOwner را پیادهسازی کند میتواند اشتراکهای LiveData، کوروتینها از طریق lifecycleScope و کار WorkManager را در پیوند با چرخه حیات مدیریت کند. این سنگ بنای معماری مدرن Android بر اساس MVVM و Jetpack است.
class MyLocationObserver(private val context: Context) : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
startLocationUpdates()
}
override fun onStop(owner: LifecycleOwner) {
stopLocationUpdates()
}
}
// در Activity:
lifecycle.addObserver(MyLocationObserver(this))
استفاده از DefaultLifecycleObserver آزمایش را سادهتر میکند، تکرار کد را کاهش میدهد و منطق چرخه حیات را بین صفحات مختلف قابل استفاده مجدد میسازد. این جایگزین مدرن بازنویسی دستی onStart/onStop در هر Activity است. در برنامههای Android توسعه یافته توسط IT Sectr، ما از LifecycleObserver برای موقعیتیابی، اسکن Bluetooth و تحلیل استفاده میکنیم — این حجم کد boilerplate را ۳۰–۴۰٪ کاهش میدهد.
پرسشهای متداول
اگر super.onCreate() یا هر متد super دیگری از چرخه حیات فراخوانی نشود، سیستم استثنای SuperNotCalledException را پرتاب میکند و برنامه با کرش سقوط میکند. این یک الزام سخت Android Runtime است — هر متد موظف است اجرا را به کلاس پایه واگذار کند، در غیر این صورت ماشین حالت داخلی نمیتواند به حالت بعدی منتقل شود.
Activity هنگام چرخش صفحه دوباره ایجاد میشود زیرا تغییر جهت — یک تغییر پیکربندی دستگاه (configuration change) است. به طور پیشفرض، Android Activity را نابود کرده و یک Activity جدید ایجاد میکند تا منابع جایگزین (layout-land، values-land) را بارگذاری کند. برای غیرفعال کردن بازآفرینی، میتوان ویژگی android:configChanges را به مانیفست اضافه کرد، اما Google استفاده از ViewModel را برای ذخیره دادهها توصیه میکند.
دادههای حیاتی در onPause() ذخیره میشوند، زیرا این آخرین متدی است که تضمین میشود قبل از اینکه برنامه توسط سیستم کشته شود فراخوانی میگردد. پس از onStop و onDestroy، سیستم میتواند فرآیند را بدون فراخوانی متدهای اضافی پایان دهد. برای پیشنویسها و دادههای موقت از SharedPreferences با apply() یا Room با کوروتین استفاده کنید.
onPause زمانی فراخوانی میشود که Activity فوکوس را از دست میدهد اما همچنان تا حدی قابل مشاهده است (مثلاً یک پنجره دیالوگ باز شده). onStop زمانی فراخوانی میشود که Activity کاملاً از صفحه توسط Activity دیگر یا با فشار دکمه «خانه» پنهان شده است. تفاوت عملی اصلی: onPause — آخرین نقطه ذخیره دادهها، onStop — مکان آزادسازی شنوندگان و سرویسهای سیستمی که در پسزمینه نیازی نیستند.
ViewModel — مؤلفه Android Jetpack که دادههای UI را ذخیره میکند و به طور خودکار از تغییرات پیکربندی (چرخش صفحه) جان سالم به در میبرد. ViewModel هنگام بازآفرینی Activity نابود نمیشود: تا زمانی که LifecycleOwner (Activity یا Fragment) به طور کامل پایان نیافته است زنده میماند. این مشکل ذخیره دادهها در هنگام چرخش صفحه بدون استفاده از Bundle و onSaveInstanceState را حل میکند. ViewModel — عنصر اجباری معماری MVVM است که توسط Google توصیه میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید