Android Kotlin Fundamentals 04.2: Karmaşık yaşam döngüsü durumları

Bu codelab, Android Kotlin Temelleri kursuna dahildir. Codelab'ler üzerinden sırayla çalışıyorsanız bu kurstan en iyi şekilde yararlanabilirsiniz. Tüm kurs codelab'leri Android Kotlin Fundamentals codelabs açılış sayfasında listelenmektedir.

Giriş

Son codelab'de, Activity ve Fragment yaşam döngüleri hakkında bilgi edindiniz. Ayrıca yaşam döngüsü durumu etkinliklerde ve parçalarda değiştiğinde çağrılan yöntemleri araştırdınız. Bu codelab'de, etkinlik yaşam döngüsünü daha ayrıntılı bir şekilde keşfedeceksiniz. Android Jetpack'in yaşam döngüsü kitaplığı hakkında da bilgi edindiniz. Bu kitaplık, yaşam döngüsü etkinliklerini daha düzenli ve bakımı kolay bir kodla yönetmenize yardımcı olabilir.

Bilmeniz gerekenler

  • Etkinliğin ne olduğu ve uygulamanızda nasıl etkinlik oluşturacağınız.
  • Activity ve Fragment yaşam döngülerinin temelleri ve bir etkinlik eyaletler arasında hareket ettiğinde çağrılan geri çağırmalar.
  • Etkinlik veya parça yaşam döngüsünde farklı zamanlarda işlemler gerçekleştirmek için onCreate() ve onStop() yaşam döngüsü geri çağırma yöntemleri geçersiz kılınır.

Neler öğreneceksiniz?

  • Yaşam döngüsü geri çağırmalarında uygulamanızın bazı bölümlerini ayarlama, başlatma ve durdurma.
  • Bir yaşam döngüsü gözlemleyicisi oluşturmak ve etkinlik ile parça yaşam döngüsünün yönetilmesini kolaylaştırmak için Android yaşam döngüsü kitaplığı nasıl kullanılır?
  • Android işlemi kapatmalar, uygulamanızdaki verileri nasıl etkiler? Android uygulamanızı kapattığında bu verileri nasıl kaydedip geri yükleyebilirsiniz?
  • Cihaz rotasyonu ve diğer yapılandırma değişikliklerinin yaşam döngüsü durumlarında nasıl değişiklik oluşturduğu ve uygulamanızın durumunu nasıl etkilediği.

Ne yaparsınız?

  • DessertClicker uygulamasını, bir zamanlayıcı işlevi içerecek şekilde değiştirin ve bu zamanlayıcıyı etkinlik yaşam döngüsü içinde çeşitli zamanlarda başlatıp durdurun.
  • Uygulamayı, Android yaşam döngüsü kitaplığını kullanacak şekilde değiştirin ve DessertTimer sınıfını yaşam döngüsü gözlemleyicisine dönüştürün.
  • Uygulamanızın süreç kapatma sürecini ve bu dönemde gerçekleşen yaşam döngüsü geri çağırmalarını simüle etmek için Android Debug Bridge'i (adb) ayarlayıp kullanın.
  • Uygulama beklenmedik bir şekilde kapanırsa kaybolabilecek uygulama verilerini saklamak için onSaveInstanceState() yöntemini uygulayın. Uygulama tekrar başladığında bu verileri geri yüklemek için kod ekleyin.

Bu codelab'de, önceki codelab'den DessertClicker uygulamasını genişletiyorsunuz. Bir arka plan zamanlayıcı ekler, ardından uygulamayı Android yaşam döngüsü kitaplığını kullanacak şekilde dönüştürürsiniz.

Önceki codelab'de, çeşitli yaşam döngüsü geri çağırmalarını geçersiz kılarak ve sistem bu geri çağırmaları çağırdığında günlüğe kaydederken etkinliği ve parça yaşam döngülerini nasıl gözlemleyeceğinizi öğrendiniz. Bu görevde, DessertClicker uygulamasında yaşam döngüsü görevlerinin yönetilmesiyle ilgili daha karmaşık bir örnek açıklanmaktadır. Saniyede kaç saniye çalıştığını belirten bir günlük ifadesi yazdıran bir zamanlayıcı kullanırsınız.

1. Adım: Tatlı Zamanlayıcı'yı kurun

  1. Son codelab'den DessertClicker uygulamasını açın. (Uygulamaya sahip değilseniz DessertClickerLogs'u buradan indirebilirsiniz.)
  2. Proje görünümünde j&ava > com.example.android.dessertclicker öğesini genişletin ve DessertTimer.kt öğesini açın. Şu anda kodun tamamının yorumlandığına dikkat edin. Bu nedenle kod, uygulamanın bir parçası olarak çalışmaz.
  3. Düzenleyici penceresinde tüm kodu seçin. Kod > Satır Yorumu ile Yorum Yap'ı seçin veya Control+/ (Mac'te Command+/) tuşuna basın. Bu komut, dosyadaki tüm kodun açıklamasını kaldırır. (Android Studio, siz uygulamayı yeniden oluşturana kadar çözümlenmemiş referans hataları gösterebilir.)
  4. DessertTimer sınıfının, zamanlayıcıyı başlatan ve durduran startTimer() ve stopTimer() öğelerini içerdiğine dikkat edin. startTimer() çalışırken zamanlayıcı, saniyede çalışan toplam saniye sayısını içeren bir günlük mesajı yazdırır. stopTimer() yöntemi, zamanlayıcıyı ve günlük ifadelerini durdurur.
  1. MainActivity.kt'yi açın. Sınıfın üst kısmında, dessertsSold değişkeninin hemen altına, zamanlayıcı için bir değişken ekleyin:
private lateinit var dessertTimer : DessertTimer;
  1. onCreate(): Aşağı kaydırın ve setOnClickListener() çağrısından hemen sonra yeni bir DessertTimer nesnesi oluşturun:
dessertTimer = DessertTimer()


Tatlı zamanlayıcı nesnesine sahip olduğunuza göre, yalnızca ekranda etkinlik varken çalışması için zamanlayıcıyı nereden başlatmanız ve durdurmanız gerektiğini düşünün. Sonraki adımlarda birkaç seçeneği inceleyebilirsiniz.

2. Adım: Zamanlayıcıyı başlatın ve durdurun

onStart() yöntemi, etkinlik görünür hale gelmeden hemen önce çağrılır. onStop() yöntemi, etkinliğin görünür hale gelmesinden sonra çağrılır. Bu geri çağırmalar, zamanlayıcının ne zaman başlatılıp durdurulacağı için iyi adaylar gibi görünür.

  1. MainActivity sınıfındaki zamanlayıcıyı onStart() geri çağırmasında başlatın:
override fun onStart() {
   super.onStart()
   dessertTimer.startTimer()

   Timber.i("onStart called")
}
  1. onStop() için zamanlayıcıyı durdur:
override fun onStop() {
   super.onStop()
   dessertTimer.stopTimer()

   Timber.i("onStop Called")
}
  1. Uygulamayı oluşturun ve çalıştırın. Android Studio'da Logcat bölmesini tıklayın. Logcat arama kutusuna dessertclicker (MainActivity ve DessertTimer sınıflarına göre filtrelenecek şekilde) girin. Uygulama başladıktan sonra zamanlayıcının da hemen çalışmaya başladığına dikkat edin.
  2. Geri düğmesini tıklayın ve zamanlayıcının tekrar durduğuna dikkat edin. Hem etkinlik hem de kontrol ettiği zamanlayıcı yok edildiği için zamanlayıcı durur.
  3. Uygulamaya dönmek için "Recents" (Son Kullanılanlar) ekranını kullanın. Logcat'te zamanlayıcının 0'dan yeniden başlatıldığına dikkat edin.
  4. Paylaş düğmesini tıklayın. Catcat'te, zamanlayıcının hâlâ çalışmaya devam ettiğini belirten bildirim.

  5. Ana Sayfa düğmesini tıklayın. Logcat'te, zamanlayıcının çalışmayı durdurduğuna dair bildirim.
  6. Uygulamaya dönmek için "Recents" (Son Kullanılanlar) ekranını kullanın. Logcat'te zamanlayıcının kaldığı yerden tekrar başladığına dikkat edin.
  7. MainActivity yönteminde, onStop() yönteminde stopTimer() çağrısına yorum yapın. stopTimer() etiketini kullandığınızda, onStart() ürününde bir işlemi başlattığınız gösterilir ancak onStop() içinde işlemi yeniden durdurmayı unutursanız.
  8. Uygulamayı oluşturup çalıştırın ve zamanlayıcı başladıktan sonra Ana sayfa düğmesini tıklayın. Uygulama arka planda olsa bile zamanlayıcı çalışıyor ve sistem kaynaklarını sürekli olarak kullanır. Zamanlayıcının çalışmaya devam etmesi, uygulamanız için bellek sızıntısı anlamına gelir. Büyük olasılıkla istediğiniz davranış aynı değildir.

    Genel olarak, geri çağırma içinde bir şey ayarladığınızda veya başlattığınızda bir çağrıyı geri çağırarak bunu durdurmanız gerekir. Bu şekilde, artık gerekli olmayan öğelerin çalışmasını engelleyebilirsiniz.
  1. onStop() için zamanlayıcıyı durdurduğunuz hattın yorumunu kaldırın.
  2. onStart() ile onCreate() arasında startTimer() çağrısını kesip yapıştırın. Bu değişiklik, bir kaynağı başlatmak için onCreate(), başlatmak için onStart() kullanmak yerine onCreate() ürününde hem kaynağı başlatıp başlattığınız durumu gösterir.
  3. Uygulamayı derleyip çalıştırın. Zamanlayıcının beklediğiniz gibi çalışmaya başladığına dikkat edin.
  4. Uygulamayı durdurmak için Ana Sayfa'yı tıklayın. Beklediğiniz gibi zamanlayıcı çalışmayı durdurur.
  5. Uygulamaya dönmek için son kullanılanlar ekranını kullanın. Bu durumda zamanlayıcının yeniden başlamadığını unutmayın. Bunun nedeni, onCreate() yalnızca uygulama başladığında çağrılmasıdır. Bir uygulama ön plana döndüğünde çağrılmaz.

Dikkat edilmesi gereken önemli noktalar:

  • Bir yaşam döngüsü geri çağırmasında kaynak oluştururken kaynağı da yıkın.
  • İlgili yöntemleri kullanarak kurulum ve yıkma işlemleri yapın.
  • onStart()'te bir özelliği ayarlarsanız onStop()'da tekrar durdurun veya yıkın.

DessertClicker uygulamasında, zamanlayıcıyı onStart() içinde başlattıysanız onStop() içinde zamanlayıcıyı durdurmanız çok kolaydır. Yalnızca bir zamanlayıcı var. Zamanlayıcıyı durdurmak kolay değil.

Daha karmaşık bir Android uygulamasında, onStart() veya onCreate() içerisinde birçok şey ayarlayabilir, ardından tümünü onStop() veya onDestroy()'da yıkabilirsiniz. Örneğin, hem kurulum hem de parçalama, başlatma ve durdurma işlemlerini yapmanız gereken animasyonlar, müzik, sensörler veya zamanlayıcılar kullanabilirsiniz. Bunu unutmanız hata ve baş ağrısına neden olur.

Android Jetpack'in bir parçası olan yaşam döngüsü kitaplığı bu görevi basitleştirir. Kitaplık, özellikle bazıları farklı yaşam döngüsü durumlarında bulunan hareketli kısımları takip etmeniz gerektiğinde kullanışlıdır. Kitaplık, yaşam döngülerinin işleyiş şeklini tersine çevirir. Etkinlik veya parça genellikle bir bileşene (DessertTimer gibi) bir yaşam döngüsü geri çağırması gerçekleştiğinde ne yapılacağını bildirir. Ancak yaşam döngüsü kitaplığını kullandığınızda bileşenin kendisi yaşam döngüsü değişikliklerini izler ve bu değişiklikler gerçekleştiğinde gerekenleri yapar.

Yaşam döngüsü kitaplığının üç ana bölümü vardır:

  • Bir yaşam döngüsü olan (ve dolayısıyla yaşam döngüsü) bileşenler olan yaşam döngüsü sahipleri. Activity ve Fragment yaşam döngüsü sahipleri. Yaşam döngüsü sahipleri LifecycleOwner arayüzünü uygular.
  • Bir yaşam döngüsü sahibinin gerçek durumunu tutan ve yaşam döngüsündeki değişiklikler olduğunda etkinlikleri tetikleyen Lifecycle sınıfı.
  • Yaşam döngüsü durumunu gözlemleyen ve yaşam döngüsü değiştiğinde görevleri gerçekleştiren yaşam döngüsü gözetimleri. Yaşam döngüsü gözlemleyicileri LifecycleObserver arayüzünü uygular.

Bu görevde DessertClicker uygulamasını dönüştürerek Android yaşam döngüsü kitaplığını kullanacak ve kitaplığın Android etkinliği ve parça yaşam döngülerinin yönetimini nasıl kolaylaştırdığını öğreneceksiniz.

1. Adım: DessertZamanlayıcı'yı bir Yaşam Döngüsü Sunucusuna dönüştürün

Yaşam döngüsü gözlemi, yaşam döngüsü kitaplığının önemli bir parçasıdır. Gözlem, sınıfların (ör. DessertTimer) etkinlik veya parça yaşam döngüsü hakkında bilgi sahibi olmasını ve yaşam döngüsü durumlarında yapılan değişikliklere yanıt olarak kendi durumunu başlatıp durdurmasını sağlar. Bir yaşam döngüsü gözlemcisiyle, nesneleri etkinlik ve parça yöntemlerinden başlatma ve durdurma sorumluluğunu kaldırabilirsiniz.

  1. DesertTimer.kt sınıfını açın.
  2. DessertTimer sınıfının sınıf imzasını aşağıdaki gibi değiştirin:
class DessertTimer(lifecycle: Lifecycle) : LifecycleObserver {

Bu yeni sınıf tanımının iki yönü vardır:

  • Oluşturucu, zamanlayıcının gözlemlediği yaşam döngüsü olan bir Lifecycle nesnesi alır.
  • Sınıf tanımında LifecycleObserver arayüzü uygulanıyor.
  1. runnable değişkeninin altında, sınıf tanımına bir init bloğu ekleyin. init blokunda, sahipten (etkinlik) aktarılan yaşam döngüsü nesnesini bu sınıfa (gözlem) bağlamak için addObserver() yöntemini kullanın.
 init {
   lifecycle.addObserver(this)
}
  1. @OnLifecycleEvent annotation ile startTimer() için ek açıklama ekleyin ve ON_STARTyaşam döngüsü etkinliğini kullanın. Yaşam döngüsü gözlemleyicinizin gözlemleyebildiği tüm yaşam döngüsü etkinlikleri Lifecycle.Event sınıfındadır.
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun startTimer() {
  1. ON_STOP etkinliğini kullanarak stopTimer() için aynı işlemi yapın:
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stopTimer()

2. Adım: MainActivity'yi değiştirin

FragmentActivity üst sınıfı LifecycleOwner uyguladığı için MainActivity sınıfınız zaten devralma yoluyla bir yaşam döngüsü sahibi. Bu nedenle, etkinliğinizin yaşam döngüsüne duyarlı olması için herhangi bir işlem yapmanız gerekmez. Tek yapmanız gereken, etkinliğin yaşam döngüsü nesnesini DessertTimer oluşturucuya iletmektir.

  1. MainActivity'yi açın. onCreate() yönteminde DessertTimer başlatma işlemini this.lifecycle içerecek şekilde değiştirin:
dessertTimer = DessertTimer(this.lifecycle)

Etkinliğin lifecycle özelliği, bu etkinliğin sahip olduğu Lifecycle nesnesini içeriyor.

  1. onCreate() içinde startTimer() çağrısını ve onStop() içinde stopTimer() çağrısını kaldırın. DessertTimer Artık yaşam döngüsünü gözlemlediğinden ve yaşam döngüsü durumu değiştiğinde otomatik olarak bilgilendirildiği için artık DessertTimer etkinliğe ne yapmanız gerektiğini söylemeniz gerekmez. Bu geri çağırmalarda tek yapmanız gereken bir mesaj kaydetmek.
  2. Uygulamayı derleyip çalıştırın ve Logcat'i açın. Zamanlayıcının beklendiği gibi çalışmaya başladığına dikkat edin.
  3. Uygulamayı arka plana almak için ana sayfa düğmesini tıklayın. Zamanlayıcının beklendiği gibi çalışmayı durdurduğuna dikkat edin.

Android, arka plandayken uygulamayı kapatırsa uygulamanıza ve verilerine ne olur? Bu zor uç durumu anlamak önemlidir.

Uygulamanız arka plana geçtiğinde yok olmaz, yalnızca durur ve kullanıcının uygulamaya geri dönmesini bekler. Ancak Android OS'in en önemli sorunlarından biri, ön plandaki etkinliğin sorunsuz bir şekilde çalışmasını sağlamak. Örneğin, kullanıcınız otobüsü yakalamasına yardımcı olacak bir GPS uygulaması kullanıyorsa GPS uygulamasını hızlı bir şekilde oluşturup yol tarifini göstermeye devam etmek önemlidir. Kullanıcının birkaç gün bakmamış olabileceği DessertClicker uygulamasını arka planda sorunsuz bir şekilde çalıştırmak daha az önemlidir.

Android, ön plan uygulamasının sorunsuz çalışabilmesi için arka plan uygulamalarını düzenler. Örneğin, Android'de arka planda çalışan uygulamaların yapabileceği işlem miktarı sınırlanır.

Bazen Android, uygulamayla ilişkili tüm etkinlikleri de içeren bir uygulama sürecini tamamen kapatır. Android, sistem stres altındayken ve görsel olarak gecikme riski altında olduğu için bu tür kapatma yapar. Dolayısıyla bu noktada ek geri çağırma veya kod çalıştırılmaz. Uygulamanızın işlemi arka planda sessizce kapatılır. Ancak kullanıcı uygulamayı kapatmış gibi görünmüyor. Kullanıcı, Android OS'in kapattığı bir uygulamaya geri döndüğünde Android, uygulamayı yeniden başlatır.

Bu görevde Android işleminin kapanmasını simüle eder ve tekrar başladığında uygulamanıza ne olduğunu incelersiniz.

1. Adım: Sürecin kapanmasını simüle etmek için adb'yi kullanın

Android Debug Bridge (adb), bilgisayarınıza bağlı emülatörlere ve cihazlara talimatlar göndermenize olanak tanıyan bir komut satırı aracıdır. Bu adımda, uygulamanızın işlemini kapatmak ve Android uygulamanızı kapattığında ne olduğunu görmek için adb özelliğini kullanırsınız.

  1. Uygulamanızı derleyip çalıştırın. Küçük kek simgesini birkaç kez tıklayın.
  2. Uygulamanızı arka plana almak için Ana sayfa düğmesine basın. Uygulamanız artık duruyor ve Android'in uygulamanın kullandığı kaynaklara ihtiyacı varsa uygulama kapatılabilir.
  3. Android Studio'da, komut satırı terminalini açmak için Terminal sekmesini tıklayın.
  4. adb yazıp Enter tuşuna basın.

    Android Debug Bridge version X.XX.X ile başlayıp tags to be used by logcat (see logcat —help ile biten çok fazla çıktı görürseniz her şey normaldir. Bunun yerine, adb: command not found komutunu görüyorsanız yürütme yolunuzda adb komutunun kullanılabildiğinden emin olun. Talimatlar için Yardımcı öğeler bölümünde "Yürütme yolunuza adb ekleyin" bölümüne bakın.
  5. Bu yorumu kopyalayıp komut satırına yapıştırın ve Return tuşuna basın:
adb shell am kill com.example.android.dessertclicker

Bu komut, tüm bağlı cihazlara veya emülatörlere, uygulamanın arka planda olması şartıyla dessertclicker paket adıyla işlemi durdurmalarını bildirir. Uygulamanız arka planda olduğundan cihazda veya emülatör ekranında işleminizin durdurulduğunu belirten hiçbir şey gösterilmez. Android Studio'da, "Uygulama sonlandırıldı" şeklinde bir mesaj görmek için Çalıştır sekmesini tıklayın." onDestroy() geri çağırma işleminin hiç çalıştırılmadığını görmek için Logcat sekmesini tıklayın. Etkinliğiniz sona erdi.

  1. Uygulamaya geri dönmek için sonlar ekranını kullanın. Uygulamanız, arka plana yerleştirilmiş veya tamamen durdurulmuş olsa bile son kullanılanlar bölümünde görünür. Uygulamaya dönmek için son kullanılanlar ekranını kullandığınızda, etkinlik tekrar başlar. Etkinlik, onCreate() dahil olmak üzere başlangıç yaşam döngüsü geri çağırmalarının tamamından geçer.
  2. Uygulama yeniden başlatıldığında, "skorunuz" (satılmış tatlı sayısı ve toplam dolar) varsayılan değerlere (0) sıfırlanır. Android, uygulamanızı kapatırsa neden durumunuzu kaydetmedi?

    OS, uygulamanızı sizin için yeniden başlattığında uygulamanızı daha önceki durumuna sıfırlamak için her türlü çabayı gösterir. Android, bazı görüntülemelerinizin durumunu alır ve etkinlikten ayrıldığınızda pakete kaydeder. Otomatik olarak kaydedilen verilere örnek olarak, EditorText'teki metin (düzende bir kimlik ayarlanmış olduğu sürece) ve etkinliğinizin arka yığınları verilebilir.

    Ancak Android OS bazen tüm verilerinizi bilmez. Örneğin, DessertClicker uygulamasında revenue gibi bir özelleştirilebilen değişkeniniz varsa Android OS bu veriyi veya etkinliğinizdeki önemini bilmez. Bu verileri gruba kendiniz eklemeniz gerekir.

2. Adım: Paket verilerini kaydetmek için onSaveInstanceState() kullanın

onSaveInstanceState() yöntemi, Android OS'nin uygulamanızı yok etmesi durumunda ihtiyacınız olabilecek verileri kaydetmek için kullandığınız geri çağırma yöntemidir. Yaşam döngüsü geri çağırma şemasında onSaveInstanceState(), etkinlik durdurulduktan sonra çağrılır. Uygulamanız arka plana her gittiğinde çağrılır.

onSaveInstanceState() çağrısını bir güvenlik önlemi olarak düşünün. Bu işlem sayesinde, etkinliğiniz ön plandan çıktıkça pakete az miktarda bilgi kaydedebilirsiniz. Sistem, uygulama kapatılıncaya kadar beklerse işletim sistemi kaynak baskısı altında olabileceğinden bu verileri şimdi kaydeder. Verilerin her defasında kaydedilmesi, gruptaki güncelleme verilerinin gerektiğinde geri yüklenmesini sağlar.

  1. MainActivity içinde onSaveInstanceState() geri çağırmasını geçersiz kılın ve bir Timber günlük ifadesi ekleyin.
override fun onSaveInstanceState(outState: Bundle) {
   super.onSaveInstanceState(outState)

   Timber.i("onSaveInstanceState Called")
}
  1. Uygulamayı oluşturup çalıştırın ve arka plana yerleştirmek için Ana Sayfa düğmesini tıklayın. onSaveInstanceState() geri çağırmasının onPause() ve onStop() etiketinden hemen sonra gerçekleştiğini unutmayın:
  2. Dosyanın üst kısmında, sınıf tanımının hemen önüne aşağıdaki sabit değerleri ekleyin:
const val KEY_REVENUE = "revenue_key"
const val KEY_DESSERT_SOLD = "dessert_sold_key"
const val KEY_TIMER_SECONDS = "timer_seconds_key"

Örnek durum paketinden hem veri kaydetmek hem de verileri almak için bu anahtarları kullanırsınız.

  1. onSaveInstanceState() bölümüne gidin ve Bundle türündeki outState parametresine dikkat edin.

    Bir paket, anahtar-değer çiftlerinden oluşan bir koleksiyondur. Burada anahtarlar her zaman dizedir. int ve boolean değerleri gibi temel değerleri gruba yerleştirebilirsiniz.
    Sistem bu paketi RAM'de sakladığından paketteki verileri küçük tutmak için en iyi uygulamadır. Bu paketin boyutu da sınırlıdır, ancak cihazdan cihaza farklılık gösterebilir. Genellikle 100 binden daha az depolama alanı kullanmanız gerekir. Aksi takdirde uygulamanız TransactionTooLargeException hatasıyla kilitlenebilir.
  2. onSaveInstanceState() olarak, putInt() değerini kullanarak revenue değerini (tam sayı) pakete yerleştirin:
outState.putInt(KEY_REVENUE, revenue)

putInt() yöntemi (ve Bundle sınıfındaki putFloat() ve putString() gibi benzer yöntemler) iki bağımsız değişken alır: Anahtar için bir dize (KEY_REVENUE sabit değeri) ve tasarruf edilecek gerçek değer.

  1. Aynı işlemi satılan tatlı sayısı ve zamanlayıcının durumuyla birlikte tekrarlayın:
outState.putInt(KEY_DESSERT_SOLD, dessertsSold)
outState.putInt(KEY_TIMER_SECONDS, dessertTimer.secondsCount)

3. Adım: Paket verilerini geri yüklemek için onCreate() öğesini kullanın

  1. onCreate() bölümüne ilerleyin ve yöntem imzasını inceleyin:
override fun onCreate(savedInstanceState: Bundle) {

onCreate() her çağrıldığında bir Bundle aldığına dikkat edin. İşleminizin kapanması nedeniyle etkinliğiniz yeniden başlatıldığında, kaydettiğiniz paket onCreate() hesabına aktarılacak. Etkinliğiniz yeni başlamışsa onCreate() grubundaki bu grup null. Yani paket null değilse önceden bilinen bir noktadan, etkinliği yeniden oluşturduğunuzu bilirsiniz.

  1. onCreate() adlı koda DessertTimer kurulumundan sonra şu kodu ekleyin:
if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
}

null testi, pakette veri olup olmadığını veya paketin null olup olmadığını belirler. Bu da uygulamanın yeni başlatılıp başlatılmadığını veya kapatıldıktan sonra yeniden oluşturulup oluşturulmadığını gösterir. Bu test, paketten veri geri yüklemek için yaygın olarak kullanılan bir kalıptır.

Burada kullandığınız anahtarın (KEY_REVENUE) putInt() için kullandığınız anahtarla aynı olduğuna dikkat edin. Her seferinde aynı anahtarı kullandığınızdan emin olmak için bu anahtarları sabit değer olarak tanımlamanız önerilir. getInt() verilerini paketten çıkarmak için olduğu gibi, verileri pakete yerleştirmek için olduğu gibi putInt() kullanırsınız. getInt() yöntemi iki bağımsız değişken alır:

  • Anahtar işlevi gören bir dize. Örneğin, gelir değeri için "key_revenue".
  • Paketteki anahtar için herhangi bir değer yoksa varsayılan değer kullanılabilir.

Paketten aldığınız tam sayı revenue değişkenine atanır ve kullanıcı arayüzünde bu değer kullanılır.

  1. Satılan tatlı sayısını ve zamanlayıcının değerini geri yüklemek için getInt() yöntemleri ekleyin:
if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
   dessertTimer.secondsCount =
       savedInstanceState.getInt(KEY_TIMER_SECONDS, 0)
}
  1. Uygulamayı derleyip çalıştırın. Donut'a geçene kadar kek düğmesine en az beş kez basın. Uygulamayı arka plana almak için Ana Sayfa'yı tıklayın.
  2. Android Studio Terminal sekmesinde adb işlemini çalıştırarak uygulamanın işlemini kapatın.
adb shell am kill com.example.android.dessertclicker
  1. Uygulamaya geri dönmek için "Recents" (Son Kullanılanlar) ekranını kullanın. Uygulamanın bu sefer doğru gelirle döndüğünü ve pakette satılan tatlı değerler bulunduğunu unutmayın. Ancak, pastanın tekrar pastaya döndüğünü unutmayın. Uygulamanın kapanmadan tam olarak kaldığı gibi geri gelmesini sağlamak için yapmanız gereken bir şey daha var.
  2. MainActivity içinde, showCurrentDessert() yöntemini inceleyin. Bu yöntemin, satılan mevcut tatlı sayısına ve allDesserts değişkenindeki tatlı listesine göre etkinlikte hangi tatlı resminin gösterileceğini belirlediğine dikkat edin.
for (dessert in allDesserts) {
   if (dessertsSold >= dessert.startProductionAmount) {
       newDessert = dessert
   }
    else break
}

Bu yöntem, doğru resmi seçmek için satılan tatlı sayısına dayanır. Bu nedenle, onSaveInstanceState()'deki paketteki resme referans vermek için herhangi bir işlem yapmanız gerekmez. Bu pakette, satılan tatlı sayısını zaten depoluyorsunuz.

  1. onCreate() içinde, durumu paketten geri yükleyen blokta şunu ara: showCurrentDessert():
 if (savedInstanceState != null) {
   revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
   dessertsSold = savedInstanceState.getInt(KEY_DESSERT_SOLD, 0)
   dessertTimer.secondsCount = 
      savedInstanceState.getInt(KEY_TIMER_SECONDS, 0)
   showCurrentDessert()                   
}
  1. Uygulamayı derleyip arka planda çalıştırın. İşlemi kapatmak için adb kullanın. Uygulamaya geri dönmek için sonlar ekranını kullanın. Hem söylenen tatlıların değerlerinin, toplam gelirin ve tatlı resminin doğru şekilde geri yüklendiğini unutmayın.

Etkinlik ve parça yaşam döngüsünün yönetilmesinde son derece özel bir durum vardır: Yapılandırma değişiklikleri, etkinliklerinizin ve parçalarınızın yaşam döngüsünü nasıl etkiler?

Bir yapılandırma değişikliği, cihaz durumu büyük ölçüde değiştiğinde sistem tarafından değişikliğin en kolay yolu etkinliği tamamen kapatıp yeniden oluşturmaktır. Örneğin, kullanıcı cihazın dilini değiştirirse tüm düzenin farklı metin yönlerine uygun olacak şekilde değişmesi gerekebilir. Kullanıcı cihazı bir yuvaya bağlarsa veya fiziksel bir klavye eklerse uygulama düzeninin farklı bir ekran boyutundan veya düzeninden yararlanması gerekebilir. Ayrıca, cihazın yönü değişirse (cihaz dikeyden yataya veya tam tersi yönde döndürülürse) düzenin yeni yöne sığacak şekilde değişmesi gerekebilir.

1. Adım: Cihaz rotasyonunu ve yaşam döngüsü geri çağırmalarını keşfedin

  1. Uygulamanızı derleyip çalıştırın ve Logcat'i açın.
  2. Cihazı veya emülatörü yatay moda döndürün. Rotasyon düğmelerini veya Control ve ok tuşlarını (Mac'te Command ve ok tuşları) kullanarak emülatörü sola veya sağa döndürebilirsiniz.
  3. Logcat'teki çıkışı inceleyin. Çıkışı MainActivity üzerinde filtreleyin.
    Cihaz veya emülatör ekranı çevirdiğinde, sistemin tüm yaşam döngüsü geri çağırmalarını çağırarak etkinliği kapatmasını sağlar. Ardından, etkinlik yeniden oluşturulurken sistem, etkinliği başlatmak için tüm yaşam döngüsü geri çağırmalarını çağırır.
  4. MainActivity içinde, onSaveInstanceState() yönteminin tamamına yorum yapın.
  5. Uygulamanızı derleyip tekrar çalıştırın. Mini kek simgesini birkaç kez tıklayın ve cihazı veya emülatörü döndürün. Bu kez cihaz döndürüldüğünde ve etkinlik kapatılıp yeniden oluşturulduğunda etkinlik, varsayılan değerlerle başlar.

    Bir yapılandırma değişikliği olduğunda, Android, uygulamanın durumunu kaydetmek ve geri yüklemek için önceki görevde öğrendiğiniz örnek durum paketini kullanır. Bir işlem kapatıldığında olduğu gibi, uygulamanızın verilerini pakete yerleştirmek için onSaveInstanceState() öğesini kullanın. Ardından, cihaz döndürüldüyse etkinlik durumu verilerini kaybetmemek için onCreate() ürününde verileri geri yükleyin.
  6. MainActivity içinde, onSaveInstanceState() yönteminin açıklamasını kaldırın, uygulamayı çalıştırın, kupayı tıklayın ve uygulamayı veya cihazı döndürün. Bu süre zarfında tatlı veriler etkinlik rotasyonu boyunca saklanır.

Android Studio projesi: DessertClickerFinal

Yaşam döngüsü ipuçları

  • Bir yaşam döngüsü geri çağırmasında bir özellik ayarlar veya başlatırsanız ilgili geri çağırmada bu öğeyi durdurun veya kaldırın. İşlemi durdurduğunuzda, artık ihtiyaç duyulmayan durumlarda çalışmaya devam etmesini önlersiniz. Örneğin, onStart() ürününde bir zamanlayıcı ayarlarsanız onStop() içindeki zamanlayıcıyı duraklatmanız veya durdurmanız gerekir.
  • onCreate() özelliğini, yalnızca uygulamanın bir kez çalıştırılan bölümlerini başlatmak için kullanın. Uygulamanızın hem uygulama başladığında hem de uygulama ön plana her döndüğünde çalıştırılan bölümlerini başlatmak için onStart() öğesini kullanın.

Yaşam döngüsü kitaplığı

  • Yaşam döngüsü kontrolünü, etkinlik veya parçadan yaşam döngüsüne duyarlı olması gereken gerçek bileşene kaydırmak için Android yaşam döngüsü kitaplığını kullanın.
  • Yaşam döngüsü sahipleri, Activity ve Fragment dahil olmak üzere yaşam döngülerine sahip (ve dolayısıyla) yaşam bileşenleridir. Yaşam döngüsü sahipleri LifecycleOwner arayüzünü uygular.
  • Yaşam döngüsü gözlemleri, mevcut yaşam döngüsü durumuna dikkat eder ve yaşam döngüsü değiştiğinde görevleri gerçekleştirir. Yaşam döngüsü gözlemleyicileri LifecycleObserver arayüzünü uygular.
  • Lifecycle nesneleri gerçek yaşam döngüsü durumlarını içerir ve yaşam döngüsü değiştiğinde etkinlikleri tetikler.

Yaşam döngüsüne duyarlı bir sınıf oluşturmak için:

  • LifecycleObserver arayüzünü yaşam döngüsüne duyarlı olması gereken sınıflara uygulayın.
  • Etkinlik veya parçadan yaşam döngüsü nesnesiyle bir yaşam döngüsü gözlemci sınıfını başlatın.
  • Yaşam döngüsü gözlemci sınıfında, yaşam döngüsü duyarlı yöntemlere, ilgilendikleri yaşam döngüsü durumu değişikliğiyle ek açıklama ekleyin.

    Örneğin, @OnLifecycleEvent(Lifecycle.Event.ON_START)ek açıklama, yöntemin onStart yaşam döngüsü etkinliğini izlediğini gösterir.

İşlemleri kapatma ve etkinlik durumunu kaydetme

  • Android, ön planda çalışan uygulamaların sorunsuz çalışabilmesi için arka planda çalışan uygulamaları düzenler. Bu düzenleme, arka plandaki uygulamaların yapabileceği işleme miktarını sınırlandırmayı ve hatta tüm uygulama sürecinizi kapatmayı içerir.
  • Kullanıcı, sistemin arka planda bir uygulamayı kapatıp kapatmadığını belirleyemez. Uygulama, son kullanılanlar ekranında görünmeye devam eder ve kullanıcının kaldığı yerden yeniden başlar.
  • Android Debug Bridge (adb), bilgisayarınıza bağlı emülatörlere ve cihazlara talimatlar göndermenize olanak tanıyan bir komut satırı aracıdır. Uygulamanızdaki bir işlemin kapanmasını simüle etmek için adb kullanabilirsiniz.
  • Android, uygulama sürecinizi kapattığında onDestroy() yaşam döngüsü yöntemi çağrılmaz. Uygulama duruyor.

Etkinlik ve parça durumunu koruma

  • Uygulamanız arka plana gittiğinde, onStop() çağrıldıktan hemen sonra uygulama verileri bir gruba kaydedilir. EditText içeriği gibi bazı uygulama verileri sizin için otomatik olarak kaydedilir.
  • Paket, anahtar ve değerlerin bir koleksiyonu olan Bundle öğesinin bir örneğidir. Anahtarlar her zaman dizedir.
  • Uygulama otomatik olarak kapatılmış olsa bile, saklamak istediğiniz pakete diğer verileri kaydetmek için onSaveInstanceState() geri çağırmasını kullanın. Verileri pakete yerleştirmek için put ile başlayan paket yöntemlerini kullanın (örneğin, putInt()).
  • onRestoreInstanceState() uygulamasından veya daha sık olarak onCreate() içinden paketin verilerini geri alabilirsiniz. onCreate() yönteminde paketi içeren bir savedInstanceState parametresi var.
  • savedInstanceState değişkeni null içeriyorsa etkinlik bir durum paketi olmadan başlamıştır ve alınacak durum verisi yoktur.
  • Paketten anahtarla veri almak için get ile başlayan Bundle gibi yöntemleri (ör. getInt()) kullanın.

Yapılandırma değişiklikleri

  • Bir yapılandırma değişikliği, cihaz durumu büyük ölçüde değiştiğinde ve sistemdeki değişikliği çözmenin en kolay yolu, etkinliği kapatıp yeniden oluşturmaktır.
  • Bir yapılandırma değişikliğinin en yaygın örneği, kullanıcının cihazı dikey moddan yatay moda veya yatay moddan dikey moda döndürmesidir. Cihaz dili değiştiğinde veya donanım klavyesi takıldığında da bir yapılandırma değişikliği söz konusu olabilir.
  • Bir yapılandırma değişikliği olduğunda Android, tüm etkinlik yaşam döngüsünü ve geri çağırma geri çağırmalarını çağırır. Daha sonra Android, etkinliği tüm yaşam döngüsü geri çağırma geri çağırma işlemlerini çalıştırarak en baştan başlatır.
  • Android, yapılandırma değişikliği nedeniyle bir uygulamayı kapattığında, onCreate() tarafından kullanılabilen durum paketi ile etkinliği yeniden başlatır.
  • İşlemin kapanmasında olduğu gibi uygulamanızın durumunu onSaveInstanceState() içindeki pakete kaydedin.

Udacity kursu:

Android geliştirici dokümanları:

Diğer:

Bu bölümde, bir eğitmen tarafından sunulan kurs kapsamında bu codelab üzerinden çalışan öğrenciler için olası ev ödevi ödevleri listelenmektedir. Öğretmenin şunları yapması gerekir:

  • Gerekirse ev ödevini atayın.
  • Öğrencilere ev ödevlerinin nasıl gönderileceğini bildirin.
  • Ev ödevlerine not verin.

Öğretmenler bu önerileri istedikleri kadar kullanabilir veya uygun görebilir ve uygun olan diğer ev ödevlerini atayabilirler.

Bu codelab'de kendiniz çalışıyorsanız, bilginizi test etmek için bu ödevlerden yararlanabilirsiniz.

Uygulamaları değiştirme

1. Ders'teki DiceRoller uygulamasını açın. (Uygulamayı indirmediyseniz buradan indirebilirsiniz.) Uygulamayı derleyip çalıştırın. Cihazı döndürdüğünüzde zarın mevcut değerinin kaybolacağını unutmayın. Paketteki bu değeri korumak için onSaveInstanceState() özelliğini uygulayın ve onCreate() içinde bu değeri geri yükleyin.

Bu soruları yanıtlayın

1. Soru

Uygulamanız, görüntülenmesi için yoğun hesaplama gerektiren bir fizik simülasyonu içeriyor. Daha sonra kullanıcı bir telefon araması alır. Aşağıdaki ifadelerden hangisi doğrudur?

  • Telefon görüşmesi sırasında, fizik simülasyonunda nesnelerin konumlarını hesaplamaya devam etmeniz gerekir.
  • Telefon araması sırasında, fizik simülasyonunda nesnelerin konumlarının durması gerekir.

2. Soru

Uygulama ekranda değilken simülasyonu duraklatmak için hangi yaşam döngüsü yöntemini geçersiz kılmanız gerekir?

  • onDestroy()
  • onStop()
  • onPause()
  • onSaveInstanceState()

3. Soru

Android yaşam döngüsü kitaplığı aracılığıyla bir sınıfın yaşam döngüsünü fark edebilmesi için sınıf hangi arayüzü uygulamalıdır?

  • Lifecycle
  • LifecycleOwner
  • Lifecycle.Event
  • LifecycleObserver

4. Soru

Hangi durumlarda etkinliğinizdeki onCreate() yöntemi, içinde veri bulunan bir Bundle alır (yani Bundle, null değildir). Birden fazla yanıt geçerli olabilir.

  • Cihaz döndürüldükten sonra etkinlik yeniden başlatılır.
  • Etkinlik sıfırdan başlatılır.
  • Etkinlik arka plandan dönüldükten sonra devam ettirilir.
  • Cihaz yeniden başlatılır.

Sonraki dersi başlatın: 5.1: ViewModel ve ViewModelFactory

Bu kurstaki diğer codelab'lerin bağlantılarına ulaşmak için Android Kotlin Fundamentals codelabs açılış sayfasına göz atın.