Yapılandırma değişikliklerini işleme

Uygulama çalışırken bazı cihaz yapılandırmaları değişebilir. Aşağıdakilerle sınırlı olmamakla birlikte bu önlemlerden bazıları şunlardır:

  • Uygulama görüntü boyutu
  • Ekran yönü
  • Yazı tipi boyutu ve kalınlığı
  • Yerel ayar
  • Koyu mod ve açık mod
  • Klavye kullanılabilirliği

Bu yapılandırma değişikliklerinin çoğu, kullanıcı etkileşimi nedeniyle gerçekleşir. Örneğin, cihazı döndürmek veya katlamak, uygulamanızın kullanabileceği ekran alanını değiştirir. Benzer şekilde, yazı tipi boyutu, dil veya tercih edilen tema gibi cihaz ayarlarında yapılan değişiklikler, Configuration nesnesinde ilgili değerleri değiştirir.

Bu parametreler genellikle uygulamanızın kullanıcı arayüzünde, Android platformunun bu parametreler değiştiğinde özel olarak tasarlanmış bir mekanizmaya sahip olması için yeterince büyük değişiklikler yapılmasını gerektirir. Bu mekanizma Activity yeniden oluşturma olarak adlandırılır.

Etkinlik yeniden oluşturma

Sistem, yapılandırma değişikliği olduğunda Activity'yi yeniden oluşturur. Bunu yapmak için sistem onDestroy() çağrısını yapar ve mevcut Activity örneğini yok eder. Ardından onCreate() kullanarak yeni bir örnek oluşturur ve bu yeni Activity örneği, yeni ve güncellenmiş yapılandırmayla başlatılır. Bu, sistemin kullanıcı arayüzünü de yeni yapılandırmayla yeniden oluşturduğu anlamına gelir.

Yeniden oluşturma davranışı, uygulamanızı yeni cihaz yapılandırmasıyla eşleşen alternatif kaynaklarla otomatik olarak yeniden yükleyerek uygulamanızın yeni yapılandırmalara uyum sağlamasına yardımcı olur.

Yeniden oluşturma örneği

Bir sayfa düzeni XML dosyasında tanımlandığı gibi android:text="@string/title" kullanarak statik bir başlık gösteren bir TextView düşünün. Görünüm oluşturulduğunda, metin geçerli dile göre tam olarak bir kez ayarlanır. Dil değişirse sistem etkinliği yeniden oluşturur. Sonuç olarak sistem, görünümü de yeniden oluşturur ve yeni dile göre doğru değere ayarlar.

Yeniden oluşturma işlemi, Activity içinde veya içinde bulunan Fragment, View veya diğer nesnelerin herhangi birinde alan olarak tutulan tüm durumları da temizler. Bunun nedeni, Activity yeniden oluşturma işleminin Activity ve kullanıcı arayüzünün tamamen yeni bir örneğini oluşturmasıdır. Ayrıca eski Activity artık görünür veya geçerli olmadığından, ona veya içerdiği nesnelere yapılan geri kalan referanslar eskidir. Bu tür hatalar, hatalara, bellek sızıntılarına ve kilitlenmelere neden olabilir.

Kullanıcı beklentileri

Uygulamanın kullanıcısı, durumun korunmasını bekler. Bir kullanıcı form doldururken bilgi almak için çoklu pencere modunda başka bir uygulamayı açarsa ve geri döndüğünde formun boş olduğunu veya uygulamanın tamamen başka bir yerine yönlendirildiğini görürse bu kötü bir kullanıcı deneyimidir. Geliştirici olarak, yapılandırma değişiklikleri ve etkinlik yeniden oluşturma yoluyla tutarlı bir kullanıcı deneyimi sunmanız gerekir.

Uygulamanızda durumun korunup korunmadığını doğrulamak için hem uygulama ön plandayken hem de arka plandayken yapılandırma değişikliklerine neden olan işlemler yapabilirsiniz. Bu işlemler aşağıdakileri içerir:

  • Cihazı döndürme
  • Çoklu pencere moduna girme
  • Çoklu pencere modunda veya serbest biçimli penceredeyken uygulamayı yeniden boyutlandırma
  • Birden fazla ekrana sahip katlanabilir cihazı katlama
  • Sistem temasını değiştirme (ör. koyu mod ve açık mod)
  • Yazı tipi boyutunu değiştirme
  • Sistem veya uygulama dilini değiştirme
  • Donanım klavyesini bağlama veya klavyenin bağlantısını kesme
  • Yerleşik istasyonu bağlama veya bağlantısını kesme

Activity Yeniden oluşturma yoluyla alakalı durumu korumak için kullanabileceğiniz üç temel yaklaşım vardır. Hangisini kullanacağınız, korumak istediğiniz durum türüne bağlıdır:

  • Karmaşık veya büyük veriler için işlem sonlandırmasını ele almak üzere yerel kalıcılık. Kalıcı yerel depolama alanı, veritabanlarını veya DataStore içerir.
  • Kullanıcı uygulamayı etkin olarak kullanırken bellekte kullanıcı arayüzüyle ilgili durumu yönetmek için ViewModel örnekleri gibi saklanan nesneler.
  • Sistem tarafından başlatılan işlem sonlandırma işlemini yönetmek ve kullanıcı girişine veya gezinmeye bağlı olan geçici durumu korumak için kayıtlı örnek durumu.

Bu API'lerin her biri hakkında ayrıntılı bilgi edinmek ve bunların ne zaman kullanılacağını öğrenmek için Kullanıcı arayüzü durumlarını kaydetme başlıklı makaleyi inceleyin.

Etkinlik yeniden oluşturmayı kısıtlama

Belirli yapılandırma değişikliklerinde otomatik etkinlik yeniden oluşturmayı engelleyebilirsiniz. Activity yeniden oluşturulması, kullanıcı arayüzünün tamamının ve Activity'ten türetilen tüm nesnelerin yeniden oluşturulmasına neden olur. Bunun için geçerli nedenleriniz olabilir. Örneğin, uygulamanızın belirli bir yapılandırma değişikliği sırasında kaynakları güncellemesi gerekmeyebilir veya performans sınırlamanız olabilir. Bu durumda, etkinliğinizin yapılandırma değişikliğini kendi başına yönettiğini beyan edebilir ve sistemin etkinliğinizi yeniden başlatmasını önleyebilirsiniz.

Belirli yapılandırma değişiklikleri için etkinlik yeniden oluşturmayı devre dışı bırakmak istiyorsanız AndroidManifest.xml dosyanızdaki <activity> girişine yapılandırma türünü android:configChanges olarak ekleyin. Olası değerler, android:configChanges özelliğinin dokümanlarında gösterilir.

Aşağıdaki manifest kodu, ekran yönü ve klavye kullanılabilirliği değiştiğinde Activity için MyActivity yeniden oluşturma işlemini devre dışı bırakır:

<activity
    android:name=".MyActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
    android:label="@string/app_name">

Bazı yapılandırma değişiklikleri, etkinliğin her zaman yeniden başlatılmasına neden olur. Bu bildirimleri devre dışı bırakamazsınız. Örneğin, Android 12L'de (API düzeyi 32) kullanıma sunulan dinamik renk değişikliği özelliğini devre dışı bırakamazsınız.

Görüntüleme sistemindeki yapılandırma değişikliklerine tepki verme

View sisteminde, Activity yeniden oluşturma işlemini devre dışı bıraktığınız bir yapılandırma değişikliği gerçekleştiğinde etkinlik Activity.onConfigurationChanged() çağrısı alır. Eklenen tüm görünümler de View.onConfigurationChanged() adresine çağrı alır. android:configChanges'ye eklemediğiniz yapılandırma değişiklikleri için sistem, etkinliği her zamanki gibi yeniden oluşturur.

onConfigurationChanged() geri çağırma yöntemi, yeni cihaz yapılandırmasını belirten bir Configuration nesnesi alır. Yeni yapılandırmanızı belirlemek için Configuration nesnesindeki alanları okuyun. Sonraki değişiklikleri yapmak için arayüzünüzde kullandığınız kaynakları güncelleyin. Sistem bu yöntemi çağırdığında etkinliğinizin Resources nesnesi, yeni yapılandırmaya göre kaynakları döndürecek şekilde güncellenir. Bu sayede sistem etkinliğinizi yeniden başlatmadan kullanıcı arayüzünüzün öğelerini sıfırlayabilirsiniz.

Örneğin, aşağıdaki onConfigurationChanged() uygulaması bir klavyenin olup olmadığını kontrol eder:

Kotlin

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    // Checks whether a keyboard is available
    if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show()
    } else if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_NO) {
        Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show()
    }
}

Java

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks whether a keyboard is available
    if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show();
    } else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO){
        Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show();
    }
}

Uygulamanızı bu yapılandırma değişikliklerine göre güncellemeniz gerekmiyorsa onConfigurationChanged() yerine onConfigurationChanged()'ü uygulayabilirsiniz. Bu durumda, yapılandırma değişikliğinden önce kullanılan tüm kaynaklar kullanılmaya devam eder ve yalnızca etkinliğinizin yeniden başlatılmasını engellemiş olursunuz. Örneğin, bir TV uygulaması, Bluetooth klavye takıldığında veya çıkarıldığında tepki vermek istemeyebilir.

Durumu koruma

Bu tekniği kullandığınızda normal etkinlik yaşam döngüsü sırasında durumu korumanız gerekir. Bunun nedeni aşağıdakilerden biri olabilir:

  • Kaçınılmaz değişiklikler: Önleyemediğiniz yapılandırma değişiklikleri uygulamanızı yeniden başlatabilir.
  • İşlem sonlandırma: Uygulamanız, sistem tarafından başlatılan işlem sonlandırma işlemlerini yönetebilmelidir. Kullanıcı uygulamanızdan ayrılırsa ve uygulama arka plana giderse sistem uygulamayı silebilir.

Jetpack Compose'da yapılandırma değişikliklerine tepki verme

Jetpack Compose, uygulamanızın yapılandırma değişikliklerine daha kolay tepki vermesini sağlar. Ancak, mümkün olduğu tüm yapılandırma değişiklikleri için Activity yeniden oluşturma özelliğini devre dışı bırakırsanız uygulamanızın yapılandırma değişikliklerini doğru şekilde işlemesi gerekir.

Configuration nesnesi, LocalConfiguration kompozisyonu yerel olarak Yazma kullanıcı arayüzü hiyerarşisinde kullanılabilir. Değişiklik olduğunda, LocalConfiguration.current kaynağından veri okuyan birleştirilebilir işlevler yeniden derlenir. Yerel kompozisyonların işleyiş şekli hakkında bilgi edinmek için CompositionLocal ile yerel kapsamlı veriler başlıklı makaleyi inceleyin.

Örnek

Aşağıdaki örnekte, bir bileşen belirli bir biçime sahip bir tarih gösterir. Kompozit, LocalConfiguration.current ile ConfigurationCompat.getLocales() çağrısını yaparak sistem yerel ayarı yapılandırma değişikliklerine tepki verir.

@Composable
fun DateText(year: Int, dayOfYear: Int) {
    val dateTimeFormatter = DateTimeFormatter.ofPattern(
        "MMM dd",
        ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
    )
    Text(
        dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
    )
}

Yerel ayar değiştiğinde Activity'nin yeniden oluşturulmasını önlemek için, Compose kodunu barındıran Activity'nin yerel ayar yapılandırma değişikliklerini devre dışı bırakması gerekir. Bunun için android:configChanges değerini locale|layoutDirection olarak ayarlayın.

Yapılandırma değişiklikleri: Temel kavramlar ve en iyi uygulamalar

Yapılandırma değişiklikleri üzerinde çalışırken bilmeniz gereken temel kavramlar şunlardır:

  • Yapılandırmalar: Cihaz yapılandırmaları, kullanıcı arayüzünün kullanıcıya nasıl gösterileceğini (ör. uygulama görüntüleme boyutu, yerel ayar veya sistem teması) tanımlar.
  • Yapılandırma değişiklikleri: Yapılandırmalar, kullanıcı etkileşimi aracılığıyla değişir. Örneğin, kullanıcı cihaz ayarlarını veya cihazla fiziksel olarak etkileşim şeklini değiştirebilir. Yapılandırma değişikliklerini önlemenin bir yolu yoktur.
  • Activity yeniden oluşturma: Yapılandırma değişiklikleri varsayılan olarak Activity yeniden oluşturulmasına neden olur. Bu, yeni yapılandırma için uygulama durumunu yeniden başlatan yerleşik bir mekanizmadır.
  • Activity imhası: Activity yeniden oluşturma işlemi, sistemin eski Activity örneğini imha edip yerine yeni bir örnek oluşturmasına neden olur. Eski örnek artık geçerli değildir. Bu sınıfa yapılan referanslar bellek sızıntısı, hata veya kilitlenmelere neden olur.
  • Durum: İki farklı nesne örneği oldukları için eski Activity örneğindeki durum, yeni Activity örneğinde mevcut değildir. Kullanıcı arayüzü durumlarını kaydetme bölümünde açıklandığı gibi uygulamanın ve kullanıcının durumunu koruyun.
  • Kapsam dışında bırakma: Bir yapılandırma değişikliği türü için etkinlik yeniden oluşturma özelliğini devre dışı bırakmak potansiyel bir optimizasyondur. Bu, uygulamanızın yeni yapılandırmaya göre düzgün şekilde güncellenmesini gerektirir.

İyi bir kullanıcı deneyimi sunmak için aşağıdaki en iyi uygulamaları uygulayın:

  • Sık sık yapılandırma değişikliklerine hazırlıklı olun: API düzeyi, form faktörü veya kullanıcı arayüzü araç setinden bağımsız olarak yapılandırma değişikliklerinin nadir olduğunu veya hiç gerçekleşmediğini varsaymayın. Kullanıcılar yapılandırma değişikliği yaptığında uygulamaların güncellenmesini ve yeni yapılandırmayla düzgün çalışmaya devam etmesini bekler.
  • Durumu koruma: Activity yeniden oluşturulduğunda kullanıcının durumunu kaybetmeyin. Durumu Kullanıcı arayüzü durumlarını kaydetme bölümünde açıklandığı şekilde koruyun.
  • Hızlı bir çözüm olarak kapsam dışında kalmayı tercih etmeyin: Durum kaybını önlemek için kısayol olarak Activity yeniden oluşturma özelliğini devre dışı bırakmayın. Etkinlik yeniden oluşturmayı devre dışı bırakmak için değişikliği ele alma sözünüzü yerine getirmeniz gerekir. Diğer yapılandırma değişikliklerinden kaynaklanan Activity yeniden oluşturma, işlemin sonlandırılması veya uygulamanın kapatılması nedeniyle durumu yine de kaybedebilirsiniz. Activity yeniden oluşturmayı tamamen devre dışı bırakmak mümkün değildir. Durumu Kullanıcı arayüzü durumlarını kaydetme bölümünde açıklandığı şekilde koruyun.
  • Yapılandırma değişikliklerini engellemeyin: Yapılandırma değişikliklerini ve Activity yeniden oluşturmayı önlemek için yön, en boy oranı veya yeniden boyutlandırılabilirlik üzerinde kısıtlamalar koymayın. Bu durum, uygulamanızı tercih ettikleri şekilde kullanmak isteyen kullanıcıları olumsuz şekilde etkiler.

Boyuta dayalı yapılandırma değişikliklerini işleme

Boyuta dayalı yapılandırma değişiklikleri herhangi bir zamanda gerçekleşebilir ve uygulamanız kullanıcıların çoklu pencere moduna girebileceği büyük ekranlı bir cihazda çalışırken daha olasıdır. Uygulamanızın bu ortamda iyi çalışmasını beklerler.

Boyut değişikliklerinin genel olarak iki türü vardır: önemli ve önemsiz. Önemli bir boyut değişikliği, ekran boyutundaki bir fark (ör. genişlik, yükseklik veya en küçük genişlik) nedeniyle yeni yapılandırma için farklı bir alternatif kaynak grubu uygulandığında gerçekleşir. Bu kaynaklar arasında uygulamanın tanımladığı kaynaklar ve kitaplıklarından herhangi birindeki kaynaklar yer alır.

Boyuta dayalı yapılandırma değişiklikleri için etkinlik yeniden oluşturmayı kısıtlama

Boyuta dayalı yapılandırma değişiklikleri için Activity yeniden oluşturma özelliğini devre dışı bıraktığınızda sistem Activity'yi yeniden oluşturmaz. Bunun yerine Activity.onConfigurationChanged() adresine bir arama alır. Ekli tüm görüntülemeler View.onConfigurationChanged() numarasına yönlendirilir.

Manifest dosyanızda android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout" varsa boyuta dayalı yapılandırma değişiklikleri için Activity yeniden oluşturma devre dışı bırakılır.

Boyuta dayalı yapılandırma değişiklikleri için etkinliğin yeniden oluşturulmasına izin verme

Android 7.0 (API düzeyi 24) ve sonraki sürümlerde, boyut değişikliği önemliyse boyuta dayalı yapılandırma değişiklikleri için Activity yeniden oluşturma yalnızca gerçekleşir. Sistem, boyut yetersiz olduğu için bir Activity yeniden oluşturmadığında bunun yerine Activity.onConfigurationChanged() ve View.onConfigurationChanged() çağrılabilir.

Activity yeniden oluşturulmadığında Activity ve View geri çağırmalarıyla ilgili dikkat edilmesi gereken bazı noktalar vardır:

  • Android 11 (API düzeyi 30) ile Android 13 (API düzeyi 33) arasında Activity.onConfigurationChanged() çağrılmaz.
  • Android 12L (API düzeyi 32) ve Android 13'ün (API düzeyi 33) ilk sürümlerinde bazı durumlarda View.onConfigurationChanged()'ün çağrılamaması bilinen bir sorundur. Daha fazla bilgi için bu herkese açık soruna göz atın. Bu sorun, daha sonraki Android 13 sürümlerinde ve Android 14'te giderilmiştir.

Boyuta dayalı yapılandırma değişikliklerini dinlemeye bağlı olan kodlar için Activity yeniden oluşturmaya veya Activity.onConfigurationChanged() kullanmaya güvenmek yerine, geçersiz kılınmış bir View.onConfigurationChanged() içeren bir View yardımcı programı kullanmanızı öneririz.