Fragment Lifecycle, Android'in bir Fragment'in yaşamı boyunca çağırdığı kesin olarak tanımlanmış bir callback metotları dizisidir: oluşturmadan (onAttach) tamamen kaldırmaya (onDetach) kadar. Fragment, Activity'den daha karmaşık bir yaşam döngüsüne sahiptir — 11 durum ve 7 ana callback içerir. Fragment Lifecycle, FragmentManager aracılığıyla yönetilir ve onu içeren Activity'nin yaşam döngüsüyle yakından ilişkilidir. Google'a göre Fragment, API Level 21+ üzerinde çalışan Android uygulamalarının %74'ünde kullanılmaktadır ve bu da profesyonel Android geliştirme için Fragment Lifecycle'ı anlamayı zorunlu kılar. Fragment Lifecycle ile ilgili Android Dokümantasyonu tüm durumları ve çağrı garantilerini açıklar.
Önemli Noktalar
Fragment Lifecycle, her Fragment örneğinin oluşturmadan yok etmeye kadar geçtiği birbirine bağlı durumlar ve metotlar kümesidir. Activity'nin aksine, Fragment'in yaşam döngüsü iki bağlama bağlıdır: Fragment'in kendisi (onAttach'tan onDetach'a kadar yaşar) ve View'i (onCreateView'dan onDestroyView'a kadar yaşar). Bu ayrım, Fragment'in temel bir özelliğidir ve Fragment'in kendisini yok etmeden ekran döndürmede View yıkımından kurtulmasını sağlar.
Fragment callback'lerinin tam dizisi:
Google'a göre, modern bir uygulamadaki ortalama fragment, kullanıcı oturumu başına 3-5 kez tam döngüden geçer (ekran döndürme ve gezinme nedeniyle). Tüm aşamaların doğru şekilde işlenmesi UI kararlılığının temelidir.
FragmentManager, Fragment'i beş ana durum aracılığıyla yönetir, Fragment.State sınıfında tanımlanmıştır. Her durum, yürütülmüş olan belirli bir callback kümesine karşılık gelir.
| Durum | Anlamı | Yürütülen Callback'ler |
|---|---|---|
| INITIALIZED | Fragment oluşturuldu, ancak View henüz mevcut değil | onAttach, onCreate |
| CREATED | View oluşturuldu, ancak Fragment görünür değil | + onCreateView, onViewCreated |
| STARTED | Fragment görünür, ancak aktif değil | + onStart |
| RESUMED | Fragment aktif, kullanıcıyla etkileşim halinde | + onResume |
| DESTROYED | Fragment yok edildi | + onDestroyView, onDestroy, onDetach |
FragmentManager, kullanıcı eylemlerine ve sistem olaylarına bağlı olarak Fragment'i durumlar arasında hareket ettirir. Bir kapsayıcıya Fragment eklerken, sırasıyla INITIALIZED → CREATED → STARTED → RESUMED geçer. Kaldırırken — RESUMED → STARTED → CREATED → DESTROYED.
CREATED durumu özeldir: View yok edilebilir (onDestroyView'dan sonra), ancak Fragment'in kendisi CREATED durumunda kalır (onDestroyView'dan sonra, onDestroy'dan önce). Bu, FragmentManager'ın Fragment'i View olmadan bellekte tutmasına izin verir ve bu, ekran döndürmelerinden kurtulmak için gereklidir.
Fragment Lifecycle ve Activity Lifecycle yakından ilişkilidir ancak temel farklılıkları vardır. Fragment her zaman bir Activity içinde yaşar ve yaşam döngüsü ana Activity'ye bağlıdır, ancak onunla aynı değildir.
| Yön | Activity | Fragment |
|---|---|---|
| Callback sayısı | 7 (onCreate … onDestroy) | 11 (onAttach … onDetach) |
| View için ayrı Lifecycle | Hayır | Evet (viewLifecycleOwner) |
| Döndürmeden kurtulur | Hayır (yok edilir) | Evet (ViewModel + Fragment kurtulur) |
| Ana bağımlılığı | Hayır | Activity Lifecycle'a bağlıdır |
| Durum kaydetme | onSaveInstanceState | onSaveInstanceState (Fragment seviyesinde) |
| Yönetim | Sistem | FragmentManager |
Ana pratik fark: ekran döndürmede, Activity tamamen yok edilir (onDestroy) ve yeniden oluşturulur (onCreate). Fragment döndürme sırasında onDestroyView (View yok edilir) → onCreateView (View yeniden oluşturulur) geçer, ancak Fragment'in kendisi ve ViewModel'i canlı kalır. Bu, Fragment'i yapılandırma değişikliklerinden kurtulması gereken UI mantığı için ideal bir kapsayıcı yapar.
Ekran döndürme sırasında çağrı sırası: Activity.onPause → Fragment.onPause → Activity.onStop → Fragment.onStop → Activity.onDestroy → Fragment.onDestroyView → (Activity yok edildi) → Activity.onCreate → Fragment.onAttach → Fragment.onCreate → Fragment.onCreateView → Fragment.onViewCreated → Activity.onStart → Fragment.onStart → Activity.onResume → Fragment.onResume.
FragmentManager, fragmentları ekleme, kaldırma, değiştirme ve durumlarını yönetmekten sorumlu merkezi sınıftır. FragmentManager, BackStack'i korur ve işlemler sırasında doğru callback sırasını garanti eder. Her Activity ve her iç içe Fragment'in kendi FragmentManager'ı vardır.
FragmentManager'ın ana işlemleri:
BackStack, FragmentManager'ın işlem yığındır. Sistem Geri düğmesine basıldığında, BackStack'teki son işlem geri alınır (popBackStack()). popBackStack ile kaldırılan bir Fragment geri yüklenir. BackStack boşsa, Geri'ye basmak Activity'yi sonlandırır.
Google'a göre, Fragment sorunlarının (çoğaltma, boş ekranlar, IllegalStateException) %78'i FragmentManager'ın yanlış kullanımıyla ilgilidir. Ana kural: işlemleri bağlama göre commit() (asenkron) veya commitNow() (senkron) aracılığıyla yürütün. commit(), birden çok işlem altında doğru sıralamayı garanti eder.
Fragment, onSaveInstanceState aracılığıyla kendi durum kaydetme mekanizmasını destekler, Activity'den bağımsız olarak çalışır. Fragment, durumu bir Bundle'da kaydeder ve geri yükleme sırasında onCreate ve onCreateView'a iletilir.
Fragment'in durumu kaydettiği durumlar:
Modern yaklaşım: Fragment durumunu kaydetmek için ViewModel'de SavedStateHandle kullanın. SavedStateHandle, manuel onSaveInstanceState gerektirmeden ekran döndürme ve işlem sonlandırmada verileri otomatik olarak kaydeder ve geri yükler. Google, Fragment'te UI durumunu kaydetmek için tercih edilen yöntem olarak SavedStateHandle'ı önerir.
setRetainInstance (Fragment 1.3'ten beri kullanımdan kaldırıldı): daha önce Fragment, ekran döndürmede setRetainInstance(true) aracılığıyla korunabiliyordu. Bu yaklaşımın yerini daha güvenilir çalışan ve özel yapılandırma gerektirmeyen ViewModel + SavedStateHandle almıştır.
viewLifecycleOwner, Fragment View'ine bağlı bir Lifecycle'dır (onCreateView'dan onDestroyView'a kadar). Bu temel olarak önemli bir kavramdır: viewLifecycleOwner aracılığıyla yapılan LiveData/Flow abonelikleri, View yok edildiğinde (onDestroyView) otomatik olarak iptal edilir, ancak Fragment'in kendisini etkilemez.
viewLifecycleOwner ve Fragment lifecycle arasındaki fark:
Bu neden önemlidir: LiveData'ya Fragment lifecycle (this) aracılığıyla abone olursanız, onDestroyView'dan sonra abonelik aktif kalır ve LiveData null bir View'i güncellemeye çalışarak NPE'ye neden olur. viewLifecycleOwner aracılığıyla abone olmak, onDestroyView'dan sonra hiçbir UI güncellemesi olmayacağını garanti eder.
Kural: Fragment'te, LiveData, Flow ve UI ile ilgili coroutine abonelikleri için her zaman viewLifecycleOwner kullanın. ViewModel coroutine'leri için viewModelScope kullanın — Fragment'e değil, ViewModel'e bağlıdır.
Doğru UI başlatma ve viewLifecycleOwner aracılığıyla LiveData aboneliğini gösterir.
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", "Liste güncelleniyor: ${users.size} kullanıcı")
}
}
override fun onDestroyView() {
super.onDestroyView()
Log.d("UserListFragment", "onDestroyView: View yok edildi")
}
}
Fragment, onCreateView'da düzeni şişirir, onViewCreated'da UI'yı yapılandırır ve LiveData'ya abone olur. viewLifecycleOwner aracılığıyla abonelik, bellek sızıntılarını önlemek için zorunlu bir gerekliliktir. onDestroyView, View yıkımını günlüğe kaydeder — Fragment'in ekran döndürmeden kurtulduğunun onayı.
Activity'de FragmentManager aracılığıyla Fragment ekleme, BackStack ile değiştirme ve geri yüklemeyi gösterir.
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", "Kullanıcı detayları yükleniyor: $userId")
}
}
Activity, fragmentları yönetmek için supportFragmentManager kullanır. BackStack ile add() işlemi, Geri tuşuna basıldığında HomeFragment'in geri yüklenmesini garanti eder. openDetail(), mevcut Fragment'i argümanlarla DetailFragment ile değiştirir. savedInstanceState == null kontrolü, ekran döndürmede fragment çoğaltmasını önler.
Tepkisel UI güncellemeleri için viewLifecycleOwner ile Fragment'te Flow ve StateFlow kullanımı.
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", "Arama sonuçları: ${results.size}")
}
}
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
}
Fragment, View'e erişmek için View Binding kullanır. viewLifecycleOwner.lifecycleScope.launch coroutine'i, View yok edildiğinde otomatik olarak iptal edilir. Sızıntıları önlemek için onDestroyView'da binding null yapılır. StateFlow, View yeniden oluşturulduğunda veri güncelliğini garanti eder.
Sıkça Sorulan Sorular
onCreateView Fragment'in kök View'ini oluşturur ve döndürür. onViewCreated, View oluşturulduktan hemen sonra çağrılır ve View'in tamamen başlatıldığını ve yapılandırmaya (findViewById, abonelikler) hazır olduğunu garanti eder. Google, onCreateView'da yalnızca düzeni şişirmeyi ve tüm UI yapılandırmasını onViewCreated'da yapmayı önerir.
onDestroy — Fragment bir nesne olarak yok edilir (ViewModel temizlenir, coroutine'ler iptal edilir). onDetach son callback'tir ve sonrasında Fragment Activity'den ayrılır. Pratikte tüm kaynaklar onDestroyView (View) ve onDestroy'da (Fragment) serbest bırakılmalıdır. onDetach, Activity'ye referansları temizlemek içindir.
Fragment, BackStack'te koruma ile bir işlem aracılığıyla FragmentManager'a eklenmemişse veya Activity onCreate'te FragmentManager'ı geri yüklemezse kaybolur. Çözüm: onCreate'te savedInstanceState == null kontrolü ile supportFragmentManager.beginTransaction().add() aracılığıyla programlı olarak Fragment ekleyin.
Hayır. Fragment her zaman FragmentManager aracılığıyla bir Activity'ye bağlıdır. Ekran döndürmede bile, Activity yeniden oluşturulur ve Fragment yeni Activity'ye yeniden bağlanır. Bir Activity dışında Fragment oluşturmak imkansızdır — Fragment oluşturucusu, sistem geri yüklemesi için boş bir oluşturucu gerektirir.
İç içe fragmentlar (nested fragments), başka bir Fragment'in içindeki Fragment'lardır. Karmaşık ekranlar oluşturmak için kullanılır: sekme panelleri, sekmeli paneller, master-detail. İç içe fragmentlar, alt FragmentManager (childFragmentManager) tarafından yönetilir. Google, performans sorunlarından kaçınmak için 2 seviyeden fazla iç içe geçmeyi önermez.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun