Fragment Lifecycle — Android-in Fragment-in həyatı boyu çağırdığı metod-kollbeklərin ciddi şəkildə müəyyən edilmiş ardıcıllığı: yaradılmadan (onAttach) tam silinməyə qədər (onDetach). Fragment Activity-dən daha mürəkkəb həyat dövrünə malikdir — 11 vəziyyət və 7 əsas kollbeki əhatə edir. Fragment Lifecycle FragmentManager vasitəsilə idarə olunur və onu ehtiva edən Activity-nin həyat dövrü ilə sıx bağlıdır. Google məlumatlarına görə, Fragment API Level 21+ ilə işləyən Android tətbiqlərinin 74%-də istifadə olunur ki, bu da Fragment Lifecycle-i başa düşməyi peşəkar Android inkişafı üçün məcburi edir. Android-in Fragment Lifecycle haqqında sənədləri bütün vəziyyətləri və çağırış zəmanətlərini təsvir edir.
Əsas məqamlar
Fragment Lifecycle — hər bir Fragment nümunəsinin yaradılmadan məhv edilməyə qədər keçdiyi bir-biri ilə əlaqəli vəziyyətlər və metodlar toplusudur. Activity-dən fərqli olaraq, Fragment-in həyat dövrü iki kontekstlə bağlıdır: Fragment-in özü (onAttach-dən onDetach-a qədər yaşayır) və onun View-i (onCreateView-dən onDestroyView-a qədər yaşayır). Bu bölünmə Fragment-in əsas xüsusiyyətidir və Fragment-in özünü məhv etmədən ekran dönməsində View-in məhv edilməsini yaşamağa imkan verir.
Fragment kollbeklərinin tam ardıcıllığı:
Google-a görə, müasir tətbiqdə orta fragment istifadəçi sessiyası ərzində 3–5 dəfə tam dövrü keçir (ekran dönmələri və naviqasiya səbəbindən). Bütün fazaların düzgün idarə edilməsi UI sabitliyinin əsasıdır.
FragmentManager Fragment-i beş əsas vəziyyət vasitəsilə idarə edir, Fragment.State sinfində müəyyən edilmişdir. Hər bir vəziyyət yerinə yetirilmiş kollbeklərin müəyyən dəstinə uyğundur.
| Vəziyyət | Mənası | Yerinə yetirilmiş kollbeklər |
|---|---|---|
| INITIALIZED | Fragment yaradılıb, lakin View hələ yoxdur | onAttach, onCreate |
| CREATED | View yaradılıb, lakin Fragment görünmür | + onCreateView, onViewCreated |
| STARTED | Fragment görünür, lakin aktiv deyil | + onStart |
| RESUMED | Fragment aktivdir, istifadəçi ilə qarşılıqlı əlaqədədir | + onResume |
| DESTROYED | Fragment məhv edilib | + onDestroyView, onDestroy, onDetach |
FragmentManager Fragment-i istifadəçi hərəkətlərindən və sistem hadisələrindən asılı olaraq vəziyyətlər arasında hərəkət etdirir. Fragment konteynerə əlavə edildikdə, o, ardıcıl olaraq INITIALIZED → CREATED → STARTED → RESUMED keçir. Silindikdə — RESUMED → STARTED → CREATED → DESTROYED.
CREATED vəziyyəti — xüsusidir: View məhv edilə bilər (onDestroyView-dən sonra), lakin Fragment-in özü CREATED vəziyyətində qalır (onDestroyView-dən sonra, onDestroy-dən əvvəl). Bu, FragmentManager-ə Fragment-i View olmadan yaddaşda saxlamağa imkan verir ki, bu da ekran dönmələrini yaşamaq üçün lazımdır.
Fragment Lifecycle və Activity Lifecycle sıx bağlıdır, lakin əsaslı fərqlərə malikdir. Fragment həmişə Activity daxilində yaşayır və onun həyat dövrü Activity-sahibindən asılıdır, lakin ona eyni deyil.
| Aspekt | Activity | Fragment |
|---|---|---|
| Kollbek sayı | 7 (onCreate … onDestroy) | 11 (onAttach … onDetach) |
| View üçün ayrıca Lifecycle | Xeyr | Bəli (viewLifecycleOwner) |
| Dönməni yaşayır | Xeyr (məhv edilir) | Bəli (ViewModel + Fragment yaşayır) |
| Hostdan asılılıq | Xeyr | Activity Lifecycle-dən asılıdır |
| Vəziyyətin saxlanması | onSaveInstanceState | onSaveInstanceState (fragment üzrə) |
| İdarəetmə | Sistem | FragmentManager |
Əsas praktik fərq: ekran dönməsində Activity tamamilə məhv edilir (onDestroy) və yenidən yaradılır (onCreate). Fragment dönmə zamanı onDestroyView (View məhv edilir) → onCreateView (View yenidən yaradılır) keçir, lakin Fragment-in özü və onun ViewModel-i canlı qalır. Bu, Fragment-i konfiqurasiya dəyişikliklərini yaşamalı olan UI məntiqi üçün ideal konteyner edir.
Ekran dönməsində çağırış ardıcıllığı: Activity.onPause → Fragment.onPause → Activity.onStop → Fragment.onStop → Activity.onDestroy → Fragment.onDestroyView → (Activity məhv edildi) → Activity.onCreate → Fragment.onAttach → Fragment.onCreate → Fragment.onCreateView → Fragment.onViewCreated → Activity.onStart → Fragment.onStart → Activity.onResume → Fragment.onResume.
FragmentManager — fraqmentlərin əlavə edilməsi, silinməsi, dəyişdirilməsi və onların vəziyyətlərinin idarə edilməsinə cavabdeh olan mərkəzi sinif. FragmentManager BackStack yığınını aparır və tranzaksiyalarda kollbeklərin düzgün ardıcıllığına zəmanət verir. Hər bir Activity və hər bir iç-içə Fragment öz FragmentManager-inə malikdir.
FragmentManager-in əsas əməliyyatları:
BackStack — FragmentManager tranzaksiyalarının yığını. Sistem „Geri" düyməsi basıldıqda BackStack-dəki son tranzaksiya geri qaytarılır (popBackStack()). popBackStack vasitəsilə silinmiş Fragment bərpa olunur. BackStack boşdursa, „Geri" basılması Activity-ni bitirir.
Google məlumatlarına görə, Fragment ilə problemlərin 78%-i (təkrarlama, boş ekranlar, IllegalStateException) FragmentManager-in düzgün istifadə edilməməsi ilə bağlıdır. Əsas qayda: tranzaksiyaları kontekstdən asılı olaraq commit() (asinxron) və ya commitNow() (sinxron) vasitəsilə yerinə yetirin. commit() çoxsaylı tranzaksiyalarda düzgün ardıcıllığa zəmanət verir.
Fragment onSaveInstanceState vasitəsilə öz vəziyyətinin saxlanması mexanizmini dəstəkləyir, Activity-dən asılı olmayaraq işləyir. Fragment vəziyyəti Bundle-də saxlayır, bərpa zamanı onCreate və onCreateView-ə ötürülür.
Fragment nə zaman vəziyyəti saxlayır:
Müasir yanaşma: Fragment vəziyyətini saxlamaq üçün ViewModel-də SavedStateHandle istifadə edin. SavedStateHandle ekran dönməsi və process death zamanı avtomatik olaraq məlumatları saxlayır və bərpa edir, əl ilə onSaveInstanceState tələb etmir. Google SavedStateHandle-i Fragment-də UI vəziyyətinin saxlanması üçün üstünlük verilən üsul kimi tövsiyə edir.
setRetainInstance (Fragment 1.3-dən köhnəlmişdir): əvvəllər Fragment ekran dönməsində setRetainInstance(true) vasitəsilə saxlanıla bilərdi. Bu yanaşma ViewModel + SavedStateHandle ilə əvəz edilmişdir ki, onlar daha etibarlı işləyir və xüsusi konfiqurasiya tələb etmir.
viewLifecycleOwner — Fragment View-i ilə bağlı Lifecycle (onCreateView-dən onDestroyView-a qədər). Bu prinsipial əhəmiyyətli konsepsiyadır: viewLifecycleOwner vasitəsilə edilən LiveData/Flow abunəlikləri View-in məhv edilməsində (onDestroyView) avtomatik ləğv edilir, lakin Fragment-in özünə təsir etmir.
viewLifecycleOwner ilə Fragment lifecycle arasındakı fərq:
Bu niyə vacibdir: əgər LiveData-ya Fragment lifecycle (this) vasitəsilə abunə olursunuzsa, onDestroyView-dən sonra abunəlik aktiv qalır və LiveData null View-i yeniləməyə çalışaraq NPE-yə səbəb olur. viewLifecycleOwner vasitəsilə abunəlik onDestroyView-dən sonra heç bir UI yeniləməsinin olmayacağına zəmanət verir.
Qayda: Fragment-də həmişə UI ilə bağlı LiveData, Flow və korutin abunəlikləri üçün viewLifecycleOwner istifadə edin. ViewModel korutinləri üçün viewModelScope istifadə edin — o, ViewModel-ə bağlıdır, Fragment-ə deyil.
UI-nin düzgün işə salınmasını və viewLifecycleOwner vasitəsilə LiveData abunəliyini nümayiş etdirir.
class UserListFragment : Fragment() {
private val viewModel: UserListViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_user_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val button: Button = view.findViewById(R.id.load_button)
button.setOnClickListener { viewModel.loadUsers() }
viewModel.users.observe(viewLifecycleOwner) { users ->
Log.d("UserListFragment", "Siyahının yenilənməsi: ${users.size} istifadəçi")
}
}
override fun onDestroyView() {
super.onDestroyView()
Log.d("UserListFragment", "onDestroyView: View məhv edildi")
}
}
Fragment onCreateView-də layout-u şişirdir, UI-ni konfiqurasiya edir və onViewCreated-də LiveData-ya abunə olur. viewLifecycleOwner vasitəsilə abunəlik — sızmaların qarşısını almaq üçün məcburi tələbdir. onDestroyView View-in məhv edilməsini qeyd edir — Fragment-in ekran dönməsini yaşadığını təsdiqləyir.
Activity-də FragmentManager vasitəsilə Fragment-in əlavə edilməsini, BackStack ilə dəyişdirilməsini və bərpasını nümayiş etdirir.
class HostActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_host)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, HomeFragment())
.addToBackStack(null)
.commit()
}
}
fun openDetail(userId: String) {
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, DetailFragment.newInstance(userId))
.addToBackStack(null)
.commit()
}
override fun onBackPressed() {
if (supportFragmentManager.backStackEntryCount > 0) {
supportFragmentManager.popBackStack()
} else {
super.onBackPressed()
}
}
}
class DetailFragment : Fragment() {
companion object {
fun newInstance(userId: String): DetailFragment {
return DetailFragment().apply {
arguments = Bundle().apply { putString("user_id", userId) }
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val userId = arguments?.getString("user_id")
Log.d("DetailFragment", "İstifadəçi detallarının yüklənməsi: $userId")
}
}
Activity fraqmentləri idarə etmək üçün supportFragmentManager istifadə edir. BackStack ilə add() tranzaksiyası „Geri" basıldıqda HomeFragment-in bərpa olunacağına zəmanət verir. openDetail() cari Fragment-i arqumentlərlə DetailFragment-ə dəyişdirir. savedInstanceState == null yoxlanışı ekran dönməsində fraqmentlərin təkrarlanmasının qarşısını alır.
UI-nin reaktiv yenilənməsi üçün Fragment-də Flow və StateFlow-un viewLifecycleOwner ilə istifadəsi.
class SearchFragment : Fragment() {
private val viewModel: SearchViewModel by viewModels()
private var binding: FragmentSearchBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentSearchBinding.inflate(inflater, container, false)
return binding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding?.searchButton?.setOnClickListener {
viewModel.search(binding?.queryInput?.text.toString())
}
viewLifecycleOwner.lifecycleScope.launch {
viewModel.searchResults.collectLatest { results ->
Log.d("SearchFragment", "Axtarış nəticələri: ${results.size}")
}
}
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
}
Fragment View-ə giriş üçün View Binding istifadə edir. viewLifecycleOwner.lifecycleScope.launch korutinası View-in məhv edilməsində avtomatik ləğv edilir. Binding sızmaların qarşısını almaq üçün onDestroyView-də sıfırlanır. StateFlow View-in yenidən yaradılmasında məlumatların aktuallığına zəmanət verir.
Tez-tez verilən suallar
onCreateView — Fragment-in kök View-ni yaradır və qaytarır. onViewCreated — View yaradıldıqdan dərhal sonra çağırılır, View-in tam işə salındığını və konfiqurasiyaya hazır olduğunu təmin edir (findViewById, abunəliklər). Google onCreateView-də yalnız layout-u şişirtməyi, bütün UI konfiqurasiyasını isə onViewCreated-də etməyi tövsiyə edir.
onDestroy — Fragment obyekt kimi məhv edilib (ViewModel təmizlənir, korutinlər ləğv edilir). onDetach — son kollbekdir, ondan sonra Fragment Activity-dən ayrılır. Praktik olaraq bütün resurslar onDestroyView (View) və onDestroy (Fragment) daxilində azad edilməlidir. onDetach — Activity-yə istinadların təmizlənməsi üçündür.
Fragment yox olur, əgər o, BackStack-də saxlanmaqla tranzaksiya vasitəsilə FragmentManager-ə əlavə edilməyibsə və ya Activity onCreate-də FragmentManager-i bərpa etmirsə. Həll yolu: Fragment-i proqramlı şəkildə onCreate-də supportFragmentManager.beginTransaction().add() vasitəsilə əlavə edin, savedInstanceState == null yoxlanışı ilə.
Xeyr. Fragment həmişə FragmentManager vasitəsilə Activity-yə bağlıdır. Hətta ekran dönməsində Activity yenidən yaradılır və Fragment yeni Activity-yə yenidən bağlanır. Fragment-i Activity xaricində yaratmaq mümkün deyil — Fragment konstruktoru sistem tərəfindən bərpa üçün boş konstruktor tələb edir.
Nested fragments (iç-içə fraqmentlər) — başqa Fragment daxilində olan Fragment. Mürəkkəb ekranlar qurmaq üçün istifadə olunur: tab panelləri, vərəq panelləri, master-detail. İç-içə fraqmentlər uşaq FragmentManager (childFragmentManager) tərəfindən idarə olunur. Google performans problemlərindən qaçmaq üçün 2 səviyyədən çox iç-içəlikdən keçməməyi tövsiyə edir.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun