LifecycleOwner — Android Jetpack kitaplığının temel bir arayüzüdür ve bir nesnenin bir yaşam döngüsüne sahip olduğunu bildirir ve getLifecycle() yöntemi aracılığıyla ona erişim sağlar. Modern Android uygulamalarının bileşen mimarisinin temelini oluşturur ve yaşam döngüsü yönetimi mantığını Activity veya Fragment'in belirli uygulamasından ayırmaya olanak tanır. Google I/O 2024 verilerine göre, Android'deki yeni projelerin %85'inden fazlası abonelikleri yönetmek ve bellek sızıntılarını önlemek için LifecycleOwner kullanıyor. Bu arayüz, LiveData, ViewModel ve diğer Jetpack bileşenlerinin temelidir ve kodun yalnızca bileşenin etkin durumunda güvenli bir şekilde yürütülmesini sağlar.
Anahtar Noktalar
LifecycleOwner — androidx.lifecycle paketinden, Lifecycle nesnesi döndüren tek bir getLifecycle() yöntemi içeren bir arayüzdür. Bu nesne, bileşenin geçerli durumunu (CREATED, STARTED, RESUMED, DESTROYED) izler ve değiştiğinde abone olan tüm gözlemcileri bilgilendirir. LifecycleOwner, Architecture Components'ın bir parçasıdır ve lifecycle-runtime kitaplığına dahildir.
Arayüzün ana görevi, yaşam döngüsüne erişimi standartlaştırmaktır. Jetpack'ten önce geliştiriciler, onStart'ta manuel abonelik ve onStop'ta abonelikten çıkma kullanıyordu, bu da kod tekrarına ve hatalara yol açıyordu. LifecycleOwner, tüm Android bileşenleri için birleşik bir mekanizma sağlayarak bu sorunu çözer. Yaşam döngüsü yöntemlerini açıkça çağırmak yerine, geliştirici bir kez Lifecycle'a abone olur ve bildirimler otomatik olarak gelir.
Arayüz, Kotlin'de tek bir soyut yöntemi olan işlevsel bir arayüz olarak bildirilmiştir:
interface LifecycleOwner {
val lifecycle: Lifecycle
}
Arayüzün işlevsel doğası sayesinde, bir temsilci veya lambda kullanarak uygulanması kolaydır. Bu, özellikle ana bilgisayarın yaşam döngüsü değişikliklerine tepki vermesi gereken Custom Views ve ViewModel sınıfları oluşturmak için uygundur. getLifecycle()'dan alınan Lifecycle nesnesi, abonelikleri yönetmek için addObserver ve removeObserver yöntemlerini sağlar.
LifecycleOwner, iki anahtar sınıfla birlikte çalışır: Lifecycle ve LifecycleObserver. Lifecycle, bileşenin geçerli durumunu bir enum State (INITIALIZED, CREATED, STARTED, RESUMED, DESTROYED) olarak saklar ve aralarındaki geçişleri izler. Durum değiştiğinde, Lifecycle kayıtlı tüm gözlemcileri bilgilendirir ve ilgili not eklenmiş yöntemleri çağırır. Bu mekanizmaya "lifecycle-aware" denir — kod yalnızca bileşen uygun bir durumdayken yürütülür.
Olay iletim mekanizması Observer desenine dayanır. LifecycleOwner, Observable olarak görev yaparken, LifecycleObserver uygulaması Observer olarak görev yapar. Activity veya Fragment, durumu değiştiğinde (onCreate → onStart → onResume → onPause → onStop → onDestroy), AndroidX sistemine otomatik olarak eklenen dahili ReportFragment mekanizması aracılığıyla Lifecycle'ı bilgilendirir. Geliştiricinin Lifecycle yöntemlerini manuel olarak çağırması gerekmez — her şey otomatik olarak gerçekleşir.
| Lifecycle Durumu | Olay | Android Yaşam Döngüsü Yöntemi |
|---|---|---|
| INITIALIZED | — | onCreate'ten önce |
| CREATED | ON_CREATE | onCreate |
| STARTED | ON_START | onStart |
| RESUMED | ON_RESUME | onResume |
| STARTED | ON_PAUSE | onPause |
| CREATED | ON_STOP | onStop |
| DESTROYED | ON_DESTROY | onDestroy |
Önemli bir detay: Lifecycle, ON_STOP ve ON_DESTROY olaylarının işlem çökmesi durumunda bile teslim edileceğini garanti eder. Bu, LifecycleOwner'ı kritik kaynakları serbest bırakmak için güvenilir bir araç haline getirir. Normal durum kaydetme için ViewModel'de SavedStateHandle kullanılması önerilir, ancak LifecycleOwner temel bir güvenlik düzeyi sağlar.
LifecycleOwner olaylarına abone olmanın iki yolu vardır: notlar içeren klasik LifecycleObserver ve açık yöntemler içeren modern DefaultLifecycleObserver. İkinci yaklaşım, daha iyi tür güvenliği sağladığı ve not yaklaşımında kullanılan yansımayı önlediği için Google tarafından 2022'den beri önerilmektedir. DefaultLifecycleObserver, Java 8+ veya Kotlin gerektirir ve yeni projeler için tercih edilir.
DefaultLifecycleObserver aracılığıyla abonelik örneği:
class MyObserver : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
// GPS izlemeyi yalnızca bileşen etkinken başlat
startLocationUpdates()
}
override fun onStop(owner: LifecycleOwner) {
// Arka plan moduna geçerken güvenli durdurma
stopLocationUpdates()
}
}
// Bağlantı:
lifecycleOwner.lifecycle.addObserver(MyObserver())
DefaultLifecycleObserver'ın her yöntemi, parametre olarak LifecycleOwner alır. Bu, gözlemcinin ayrıca iletmek zorunda kalmadan çalışan bileşenin bağlamına erişmesini sağlar. Bu yaklaşım, kodu daha modüler ve test edilebilir hale getirir — Observer, belirli bir Activity veya Fragment uygulamasına bağlı değildir, LifecycleOwner soyutlamasıyla çalışır.
@OnLifecycleEvent notu kullanan eski yöntem hâlâ eski projelerde bulunur, ancak yeni kod için önerilmez. Notları işlemek için gereken yansıma, ek yük getirir ve derleme zamanında tespit edilemeyen hatalara yol açabilir. Google resmi olarak DefaultLifecycleObserver'a geçişi tavsiye eder.
// Eski yaklaşım — yeni projeler için önerilmez
class MyLegacyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
startLocationUpdates()
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
stopLocationUpdates()
}
}
Not yaklaşımının önemli bir dezavantajı vardır: Observer'ın yaşam süresi kontrolünün olmaması. Geliştirici, LifecycleOwner yok edildiğinde Observer'ın aboneliğini iptal etmeyi unutursa, çöp toplayıcı çağrılana kadar Observer nesnesi bellekte kalır. DefaultLifecycleObserver bu sorunu çözer — Observer, Lifecycle'a bağlanır ve DESTROYED durumuna geçişte otomatik olarak abonelikten çıkar.
AppCompat 1.1.0 ve AndroidX Fragment 1.2.0'dan itibaren, AppCompatActivity veya Fragment'ten miras alan tüm Activity ve Fragment'ler otomatik olarak LifecycleOwner olur. Bu, getLifecycle() yönteminin varsayılan olarak kullanılabilir olduğu ve yaşam döngüsü olaylarına aboneliğin ek yapılandırma olmadan çalıştığı anlamına gelir. Geliştiricinin yalnızca Activity veya Fragment içinde herhangi bir yerden lifecycle.addObserver() çağırması yeterlidir.
Activity'de LifecycleOwner entegrasyonu örneğini inceleyelim:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(LocationObserver(this))
}
}
Bu örnekte, lifecycle, AndroidX Activity sayesinde kullanılabilen bir extension property'dir. LocationObserver gözlemcisi, Activity'nin başlangıcı (ON_START) ve duruşu (ON_STOP) hakkında otomatik olarak bildirim alacaktır. Ekran döndürüldüğünde, Observer ON_DESTROY ve ardından ON_CREATE hakkında bilgilendirilir ve bu da ek kod olmadan yapılandırma değişikliklerinin doğru şekilde işlenmesini sağlar.
Fragment, arayüz aracılığıyla LifecycleOwner'ı uygular ve Lifecycle'ı, üst Activity'ye değil Fragment'in yaşam döngüsüne bağlanır. Bu önemlidir: Fragment'in Lifecycle'ı, Fragment işlemden kaldırıldığında DESTROYED durumuna geçerken, Activity RESUMED durumunda kalabilir. Bu fark, Observer'ın her bileşenin yaşam döngüsüne ayrı ayrı abone olmasına olanak tanır.
class MyFragment : Fragment() {
private val uiStateObserver = UiStateObserver()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lifecycle.addObserver(uiStateObserver)
}
}
Fragment'te LifecycleOwner kullanmanın önemli bir avantajı, Fragment DESTROYED durumuna geçtiğinde otomatik abonelik iptalidir. Bu, özellikle Fragment'lerin dinamik olarak oluşturulup yok edilebildiği ViewPager için önemlidir. Bu senaryoda manuel abonelik yönetimi son derece karmaşık ve hataya açık olurdu.
LifecycleOwner arayüzü, yaşam döngüsü olan herhangi bir sınıfta uygulanabilir. Bu, Custom Views, Services ve hatta bazı mimari çözümlerde ViewModel için kullanışlıdır. Google, Lifecycle'ın durumunu yöneten ve olaylar oluşturan yardımcı sınıf LifecycleRegistry'yi sağlar. Bileşenin durumu değiştiğinde geliştiricinin LifecycleRegistry'nin ilgili yöntemlerini manuel olarak çağırması gerekir.
Custom View'da LifecycleOwner uygulaması örneği:
class MyCustomView(
context: Context,
attrs: AttributeSet?
) : FrameLayout(context, attrs), LifecycleOwner {
private val lifecycleRegistry = LifecycleRegistry(this)
override val lifecycle: Lifecycle
get() = lifecycleRegistry
fun onStart() {
lifecycleRegistry.setCurrentState(Lifecycle.State.STARTED)
}
fun onStop() {
lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED)
}
}
Bu örnekte, LifecycleRegistry bir durum deposu olarak işlev görür. onStart/onStop yöntemleri, Custom View görünür hale geldiğinde veya gizlendiğinde üst bileşen (örneğin Activity) tarafından çağrılmalıdır. LifecycleRegistry, durumlar arasındaki geçiş için gerekli olayları otomatik olarak hesaplar ve abone olan tüm Observer'ları bilgilendirir.
Kendi LifecycleOwner'ınızı uygularken kurala uymak önemlidir: LifecycleRegistry'nin durumu, diğer tüm işlemlerden sonra ilgili yaşam döngüsü yönteminde en son güncellenmelidir. Bu, bileşen yeni duruma tamamen hazır olduğunda Observer'ın bildirim almasını sağlar. Alternatif olarak LifecycleRegistry.createUnsafe kullanmak da mümkündür, ancak iş parçacıkları konusunda dikkatli olunmalıdır.
LifecycleOwner, birkaç önemli Android Jetpack bileşeninin temelidir. LiveData, etkin durumu belirlemek ve bileşen yok edildiğinde otomatik olarak abonelikten çıkmak için LifecycleOwner kullanır. ViewModel, doğrudan LifecycleOwner'ı uygulamaz ancak SavedStateHandle aracılığıyla Lifecycle alabilir. Navigation Component, NavBackStackEntry'de abonelikleri yönetmek için LifecycleOwner kullanır. Bu ilişkiyi anlamak, sağlam bir temel üzerinde uygulama mimarisi oluşturmaya yardımcı olur.
LiveData'nın LifecycleOwner ile etkileşimi:
class ExampleActivity : AppCompatActivity() {
private val viewModel: ExampleViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.userData.observe(this) { data ->
// this — LifecycleOwner (Activity)
// Kod yalnızca Activity RESUMED durumundayken yürütülür
updateUI(data)
}
}
}
LiveData, observe() yönteminde LifecycleOwner gerektirir çünkü bu, kullanıcı arayüzü güncellemelerinin yalnızca etkin durumda gerçekleşmesini garanti eder. Activity arka plandaysa, LiveData son değeri korur ancak Observer'ı bilgilendirmez. RESUMED durumuna dönüldüğünde, Observer ek ağ veya veritabanı isteği olmadan güncel değeri alır.
DataBinding de observable alanları Activity veya Fragment'in yaşam döngüsüne bağlamak için LifecycleOwner kullanır. Bu, ViewModel + DataBinding kombinasyonunda bellek sızıntılarını önlemeye olanak tanır — LifecycleOwner yok edildiğinde tüm abonelikler otomatik olarak temizlenir. Bu yaklaşım, kodu bildirimsel ve güvenli hale getirir.
LifecycleOwner'ın doğru kullanımı, birkaç temel kurala uymayı gerektirir. Birinci ve en önemlisi: Observer'ı her zaman onCreate/onViewCreated'da abone yapın, daha sonra değil. Bu, Observer'ın Lifecycle'ın başlangıç durumunu (onCreate'ten sonra CREATED) almasını ve olayları kaçırmamasını sağlar. İkinci kural: tüm yeni projeler için not yaklaşımı yerine DefaultLifecycleObserver kullanın.
Coroutine'ler ve LifecycleOwner ile çalışmanın modern yaklaşımı — repeatOnLifecycle eklentisi:
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.flow.collect { value ->
updateUI(value)
}
}
}
Bu desen, Flow üzerindeki collect işleminin yalnızca STARTED veya RESUMED durumunda etkin olmasını garanti eder. STOPPED durumuna geçildiğinde koleksiyon otomatik olarak iptal edilir ve STARTED durumuna dönüldüğünde yeniden başlatılır. repeatOnLifecycle, Fragment'te Flow'dan manuel abonelik iptalinin yerini alır ve kullanıcı arayüzü bileşenlerinde eşzamansız veri akışlarıyla çalışmak için Google tarafından önerilen yaklaşımdır.
Bir diğer önemli öneri: yaşam döngüsüyle ilgili olmayan mantık için LifecycleObserver'ı kötüye kullanmayın. Bir bileşen belirli bir durumda bir eylem gerçekleştirmeli ancak yok edildiğinde abonelik iptali gerektirmiyorsa, onStart/onStop'ta açık yöntem çağrıları kullanmak daha iyidir. LifecycleObserver, manuel abonelik yönetiminin karmaşık ve hataya açık olduğu uzun ömürlü bileşenler (LocationListener, SensorManager) için uygundur.
Sıkça Sorulan Sorular
LifecycleOwner — bir nesnenin bir yaşam döngüsüne sahip olduğunu bildiren bir arayüzdür. Lifecycle — geçerli durumu saklayan ve Observer'ları yöneten bir sınıftır. LifecycleOwner, getLifecycle() aracılığıyla Lifecycle'ı sağlar.
Hayır, Lifecycle DESTROYED durumuna geçişte tüm Observer'ları otomatik olarak abonelikten çıkarır. Bu, LifecycleOwner'ın ana avantajlarından biridir — geliştiricinin onDestroy'te manuel olarak removeObserver çağırması gerekmez.
Fragment, AndroidX fragment arayüzü aracılığıyla LifecycleOwner'ı uygular. Lifecycle'ı, Activity'den ayrı olarak Fragment'in yaşam döngüsüne bağlanır. Bu, Observer'ın üst Activity yerine Fragment'in olaylarına tepki vermesini sağlar.
Evet, bunun için LifecycleRegistry kullanılır. Custom View, LifecycleOwner arayüzünü uygulamalı ve görünürlük veya pencereye eklenme değiştiğinde LifecycleRegistry'nin durumunu manuel olarak güncellemelidir.
LifecycleOwner farklı bir sorunu çözer: yaşam döngüsü olaylarına abonelik yönetimi, coroutine iptali değil. Coroutine'ler için, LifecycleOwner yok edildiğinde çalışan coroutine'leri otomatik olarak iptal eden lifecycleScope kullanılır.
Ö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