onCreate — اولین و تنها متد اجباری چرخه حیات Activity و Fragment در Android است. سیستم یک بار هنگام ایجاد کامپوننت آن را فراخوانی میکند و پارامتر Bundle را با وضعیت ذخیرهشده قبلی ارسال میکند. درون onCreate توسعهدهنده رابط کاربری را مقداردهی اولیه میکند، عناصر View را متصل میکند، کنترلکنندههای رویداد را پیکربندی میکند و دادهها را از savedInstanceState بازیابی میکند. بدون پیادهسازی صحیح onCreate نمیتوان هیچ برنامه Android را اجرا کرد — این نقطه ورود برای هر صفحه است. درباره چرخه حیات کلی Activity در مقاله Activity Lifecycle بیشتر بخوانید.
نکات اصلی
onCreate — متد فراخوان (callback) است که Android هنگام ایجاد یک نمونه جدید از Activity یا Fragment آن را فراخوانی میکند. این اولین نقطه ورود به کد صفحه کاربر است: قبل از فراخوانی onCreate هیچ کد کاربری اجرا نمیشود. سیستم پارامتر Bundle را به متد ارسال میکند که یا حاوی دادههای ذخیرهشده قبلی است (در هنگام بازسازی) یا برابر null است (در اولین راهاندازی).
متد onCreate در کلاس android.app.Activity و در کلاس androidx.fragment.app.Fragment تعریف شده است. هر دو variant وظایف مشابهی را انجام میدهند: مقداردهی اولیه کامپوننت، پیکربندی UI و بازیابی وضعیت. با این حال پیادهسازی خاص متفاوت است — Activity از setContentView برای بارگذاری چیدمان استفاده میکند، در حالی که Fragment از طریق onCreateView View را برمیگرداند. توسعهدهنده موظف است حداقل onCreate را در Activity بازنویسی کند — بدون این Android نمیتواند صفحه را نمایش دهد.
onCreate دقیقاً یک بار در طول چرخه حیات کامل نمونه Activity فراخوانی میشود. حتی هنگام چرخش صفحه، نمونه جدید Activity یک فراخوانی جدید onCreate با Bundle از نمونه قبلی دریافت میکند. این ویژگی onCreate را به مکان ایدهآلی برای مقداردهی اولیه یکباره تبدیل میکند: بارگذاری دادهها، ایجاد آداپتورها، پیکربندی کامپوننتهای DI از طریق Dagger یا Hilt.
در Activity متد onCreate چهار وظیفه کلیدی را انجام میدهد: بارگذاری چیدمان layout، مقداردهی اولیه عناصر View، بازیابی وضعیت از Bundle و پیکربندی کنترلکنندههای اولیه رویداد. حداقل کد اجباری در onCreate — فراخوانی super.onCreate(savedInstanceState) و setContentView(R.layout.activity_main).
class MainActivity : AppCompatActivity() {
private var binding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ViewBinding — جایگزین مدرن findViewById
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding?.root)
// مقداردهی اولیه با استفاده از binding
binding?.apply {
welcomeText.text = getString(R.string.welcome)
startButton.setOnClickListener { startGame() }
}
// بازیابی وضعیت
if (savedInstanceState != null) {
score = savedInstanceState.getInt("score", 0)
binding?.scoreText?.text = score.toString()
}
}
}
روش مدرن — استفاده از ViewBinding به جای findViewById. ViewBinding کلاس ActivityMainBinding را در مرحله کامپایل تولید میکند که خطاهای مربوط به IDهای نادرست را حذف کرده و حجم کدهای تکراری را کاهش میدهد. Google از Android Studio 3.6 به بعد ViewBinding را به عنوان روش استاندارد دسترسی به View در Activity و Fragment توصیه میکند.
ترتیب اقدامات در onCreate باید دقیق باشد: ابتدا super، سپس setContentView، سپس بقیه موارد. فراخوانی findViewById قبل از setContentView null برمیگرداند — چیدمان هنوز بارگذاری نشده و عناصر View در سلسلهمراتب وجود ندارند. این یکی از رایجترین خطاهای توسعهدهندگان مبتدی Android است.
onCreate در Fragment با Activity متفاوت است: در اینجا setContentView فراخوانی نمیشود و فقط مقداردهی اولیه دادههای غیرمرتبط با UI انجام میشود. Fragment ایجاد کامپوننت و ایجاد View را به دو متد جداگانه تقسیم میکند: onCreate (یک بار فراخوانی میشود) و onCreateView (هر بار هنگام ایجاد یا بازسازی View فراخوانی میشود).
class UserListFragment : Fragment() {
private lateinit var viewModel: UserViewModel
private var binding: FragmentUserListBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// مقداردهی اولیه ViewModel — از بازسازی View عبور میکند
viewModel = ViewModelProvider(this)[UserViewModel::class.java]
// آرگومانهای FragmentManager
arguments?.let {
viewModel.loadUser(it.getString("user_id") ?: "")
}
// ذخیره در هنگام چرخش
retainInstance = true
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentUserListBinding.inflate(inflater, container, false)
return binding!!.root
}
}
تفاوت کلیدی بین onCreate Activity و Fragment: onCreate در Fragment نباید حاوی کد مرتبط با View باشد، زیرا View ممکن است نابود و دوباره ایجاد شود (مثلاً هنگام جابجایی بین تبهای ViewPager)، در حالی که onCreate فقط یک بار فراخوانی میشود. بارگذاری دادهها، پیکربندی ViewModel و مقداردهی اولیه آداپتورها — وظایف onCreate هستند، در حالی که اتصال View — وظیفه onViewCreated است.
پارامتر savedInstanceState در onCreate — مکانیزم ذخیره و بازیابی وضعیت موقت Activity یا Fragment است. وقتی سیستم Activity را نابود میکند (چرخش صفحه، کمبود حافظه)، onSaveInstanceState() را فراخوانی میکند که توسعهدهنده یک جفت کلید-مقدار در Bundle قرار میدهد. هنگام ایجاد نمونه جدید، این Bundle در onCreate بازگردانده میشود.
Bundle از انواع داده زیر پشتیبانی میکند: String، Integer، Boolean، Long، Float، Double، آرایههای آنها، همچنین اشیاء Parcelable و Serializable. برای اشیاء پیچیده از Parcelable استفاده میشود — این مکانیزم سریالسازی کارآمدتری است که مخصوص Android است. اندازه Bundle تقریباً به ۵۰۰ کیلوبایت محدود است — تجاوز از حد باعث ایجاد استثنای TransactionTooLargeException میشود.
companion object {
private const val KEY_USER_NAME = "user_name"
private const val KEY_SCORE = "score"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_game)
if (savedInstanceState != null) {
userName = savedInstanceState.getString(KEY_USER_NAME) ?: ""
currentScore = savedInstanceState.getInt(KEY_SCORE)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString(KEY_USER_NAME, userName)
outState.putInt(KEY_SCORE, currentScore)
}
درک این نکته مهم است: onSaveInstanceState زمانی که کاربر بهطور صریح Activity را از طریق finish() یا دکمه «بازگشت» میبندد فراخوانی نمیشود. سیستم معتقد است که در این حالت کاربر آگاهانه کار را پایان میدهد و ذخیره وضعیت لازم نیست. بنابراین نمیتوان برای ذخیرهسازی طولانیمدت دادهها تنها به savedInstanceState متکی بود — از Room، DataStore یا SharedPreferences استفاده کنید.
onCreate در رشته اصلی (UI) اجرا میشود و سیستم منتظر میماند تا قبل از نمایش Activity روی صفحه به پایان برسد. اگر onCreate بیش از ۵ ثانیه طول بکشد، سیستم یک دیالوگ ANR (Application Not Responding) نشان میدهد و به کاربر پیشنهاد بستن برنامه را میدهد. عملیات طولانی مانند بارگذاری داده از شبکه یا خواندن از پایگاه داده باید به رشته پسزمینه منتقل شوند.
طبق توصیههای Google Android Performance (2025)، onCreate باید در کمتر از ۱ ثانیه در دستگاههای میانرده به پایان برسد. برای این منظور باید: از مقداردهی اولیه تنبل (delegate lazy در Kotlin) استفاده کنید، بارگذاری دادههای سنگین را به onResume یا از طریق کوروتینها به تعویق بیندازید، از ViewStub برای کامپوننتهای UI کماستفاده به کار ببرید، زمان راهاندازی را از طریق Android Vitals پروفایل کنید.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// مقداردهی اولیه تنبل — شیء فقط در اولین مراجعه ایجاد میشود
val heavyData by lazy {
HeavyDataLoader.load()
}
// بارگذاری داده در رشته پسزمینه از طریق lifecycleScope
lifecycleScope.launch(Dispatchers.IO) {
val users = userDao.getAllUsers()
withContext(Dispatchers.Main) {
adapter.submitList(users)
}
}
}
ابزارهای پروفایلینگ: Android Studio Profiler (برگه CPU) زمان دقیق اجرای هر متد را نشان میدهد. در Android Vitals (کنسول Google Play) میتوان معیار «زمان راهاندازی سرد» را ردیابی کرد — اگر onCreate Activity شما از ۵۰۰ میلیثانیه بیشتر شود، کنسول آن را به عنوان مشکل عملکرد علامتگذاری میکند. ما در IT Sectr از تستهای Macrobenchmark برای کنترل خودکار زمان راهاندازی هر Activity در خط لوله CI استفاده میکنیم.
ViewModel — بهترین روش مقداردهی اولیه دادهها در onCreate که باید چرخش صفحه را تحمل کنند. ViewModel در onCreate از طریق ViewModelProvider ایجاد میشود و بهطور خودکار هنگام تغییر پیکربندی حفظ میشود. وقتی Activity پس از چرخش بازسازی میشود، ViewModel در حافظه باقی میماند و onCreate همان ViewModel را بدون از دست دادن داده دریافت میکند.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile)
// ViewModel یک بار ایجاد میشود و تغییرات پیکربندی را تحمل میکند
val viewModel: ProfileViewModel =
ViewModelProvider(this)[ProfileViewModel::class.java]
// مشاهده LiveData — UI هنگام تغییر داده بهطور خودکار بهروز میشود
viewModel.user.observe(this) { user ->
binding?.userName?.text = user.name
binding?.userEmail?.text = user.email
}
// بارگذاری داده اگر ViewModel تازه ایجاد شده است
if (savedInstanceState == null) {
viewModel.loadProfile(userId)
}
}
ترکیب ViewModel + LiveData/StateFlow مشکل چرخش صفحه را بدون ذخیره دستی در Bundle حل میکند. ViewModel دادهها را در حافظه نگه میدارد، LiveData بهطور خودکار Activity را هنگام بازسازی دوباره مشترک میکند، و StateFlow (از Kotlin Coroutines) با پشتیبانی از کوروتینها واکنشگرایی را اضافه میکند. این معماری استانداردی است که Google در راهنمای Guide to App Architecture توصیه میکند.
حتی توسعهدهندگان با تجربه در onCreate خطاهای معمولی مرتکب میشوند. بیایید پنج مشکل رایج و روشهای اجتناب از آنها را بررسی کنیم.
رایجترین خطا — تلاش برای یافتن View از طریق findViewById قبل از فراخوانی setContentView. همه عناصر View در لحظه inflate چیدمان ایجاد میشوند، بنابراین هر مراجعه به findViewById قبل از setContentView null برمیگرداند و هنگام تلاش برای استفاده از View باعث NullPointerException میشود. راهحل: ترتیب دقیق — ابتدا super، سپس setContentView، بعد findViewById یا ViewBinding.
بارگذاری داده از شبکه، خواندن از پایگاه داده یا پردازش آرایههای بزرگ بهطور مستقیم در onCreate رندر فریم اول را مسدود میکند. کاربر تا پایان یافتن onCreate یک صفحه سیاه میبیند که درک سرعت برنامه را کاهش میدهد. راهحل: برای عملیات ناهمگام از lifecycleScope.launch استفاده کنید، تا پایان بارگذاری یک اسکلتون (placeholder UI) نمایش دهید.
اگر هنگام چرخش صفحه وضعیت از Bundle بازیابی نشود، کاربر تمام ورودی ذخیرهنشده را از دست میدهد: متن در فیلدهای فرم، موقعیت اسکرول، عناصر انتخابشده. راهحل: همیشه savedInstanceState != null را در onCreate برای بازیابی دادهها بررسی کنید، حتی اگر به نظر میرسد از دست دادن وضعیت بعید است.
کلاسهای ناشناس و لامبداها در onCreate میتوانند بهطور ضمنی پس از نابودی Activity به آن ارجاع نگه دارند. مثلاً Handler ایجاد شده در onCreate به اجرای وظایف بهتعویقافتاده حتی پس از نابودی Activity ادامه میدهد. راهحل: از LifecycleObserver، ViewModel و lifecycleScope استفاده کنید که وظایف را هنگام نابودی بهطور خودکار لغو میکنند.
مقداردهی اولیه View در onCreate Fragment — یک خطای منطقی است، زیرا View ممکن است بدون فراخوانی onCreate دوباره ایجاد شود. اگر شنوندهای در onCreate تنظیم شود و View در onCreateView متصل شود، هنگام بازسازی شنونده روی View قدیمی باقی میماند. راهحل: تمام کار با View را در onViewCreated انجام دهید و onCreate را فقط برای مقداردهی اولیه لایه داده نگه دارید.
سوالات متداول
بله، بازنویسی onCreate اجباری است برای هر Activity که رابط کاربری را نمایش میدهد. بدون این نمیتوان setContentView را فراخوانی کرد و چیدمان XML را بارگذاری کرد. اگر Activity UI ندارد (مثلاً Activity-پوشش شفاف)، onCreate همچنان بازنویسی میشود اما بدون فراخوانی setContentView.
خیر، onCreate نمیتواند برای همان نمونه Activity دوباره فراخوانی شود. اگر Activity نابود و دوباره ایجاد شود (چرخش صفحه، کمبود حافظه)، این یک نمونه جدید با فراخوانی جدید onCreate است. استثنا — متد recreate() که بهطور اجباری Activity را نابود و بازسازی میکند، اما این نیز ایجاد یک نمونه جدید است.
اگر super.onCreate(savedInstanceState) فراخوانی نشود، Android Runtime استثنای SuperNotCalledException را پرتاب میکند و برنامه crash میکند. سیستم بهطور دقیق الزام میکند که هر متد بازنویسیشده چرخه حیات نسخه super خود را فراخوانی کند — این کار صحیح ماشین حالت داخلی را تضمین میکند.
تفاوت اصلی: onCreate در Activity UI را از طریق setContentView بارگذاری میکند، در حالی که onCreate در Fragment فقط دادهها را مقداردهی اولیه میکند. Fragment View را در متد جداگانه onCreateView ایجاد میکند که ممکن است多次 فراخوانی شود (مثلاً هنگام جابجایی بین تبها)، در حالی که onCreate Fragment یک بار در طول عمر نمونه Fragment فراخوانی میشود.
دادههای مقداردهیاولیهشده در onCreate در فیلدهای کلاس Activity یا Fragment ذخیره میشوند. مثلاً private lateinit var binding: ActivityMainBinding در سطح کلاس اعلام، در onCreate مقداردهی اولیه و در تمام متدهای بعدی قابل دسترس است. برای دادههایی که چرخش صفحه را تحمل میکنند از ViewModel با LiveData یا StateFlow استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید