Performans sorunlarına neden olan kararsız bir sınıfla karşılaştığınızda sınıfı kararlı hale getirmeniz gerekir. Bu dokümanda, bunu yapmak için kullanabileceğiniz çeşitli teknikler özetlenmektedir.
Güçlü atlama özelliğini etkinleştir
Öncelikle güçlü atlama modunu etkinleştirmeyi denemelisiniz. Güçlü atlama modu, kararsız parametrelere sahip composable'ların atlanmasına olanak tanır ve kararlılıktan kaynaklanan performans sorunlarını düzeltmenin en kolay yöntemidir.
Daha fazla bilgi için Güçlü atlama konusuna bakın.
Sınıfı sabit hale getirin
Kararsız bir sınıfı tamamen değiştirilemez hale getirmeyi de deneyebilirsiniz.
- Sabit: İlgili türdeki bir örnek oluşturulduktan sonra herhangi bir özelliğin değerinin hiçbir zaman değiştirilemeyeceği ve tüm yöntemlerin şeffaf olduğu bir türü belirtir.
- Sınıfın tüm özelliklerinin
var
yerineval
ve sabit türde olduğundan emin olun. String, Int
veFloat
gibi temel türler her zaman sabittir.- Bu imkansızsa değişken özellikler için Oluştur durumunu kullanmanız gerekir.
- Sınıfın tüm özelliklerinin
- Kararlı: Değişebilir olan bir türü gösterir. Compose çalışma zamanı, türün herkese açık mülklerinin veya yöntem davranışının bir önceki çağrıdan farklı sonuçlar verip vermeyeceğini ve ne zaman gerçekleşeceğini bilmez.
Sabit koleksiyonlar
Compose'un bir sınıfı kararsız olarak kabul etmesinin yaygın bir nedeni koleksiyonlardır. Kararlılık sorunlarını teşhis edin sayfasında belirtildiği gibi, Compose derleyicisi List, Map
ve Set
gibi koleksiyonların gerçekten sabit olduğundan tam olarak emin olamaz ve bu nedenle onları kararsız olarak işaretler.
Bu sorunu çözmek için sabit koleksiyonları kullanabilirsiniz. Compose derleyicisi Kotlinx Sabit Koleksiyonları için destek içerir. Bu koleksiyonların sabit olduğu garanti edilir ve Compose derleyicisi bunları bu şekilde ele alır. Bu kitaplık hâlâ alfa sürümünde olduğundan API'sinde değişiklikler olabilir.
Kararlılık sorunlarını teşhis etme kılavuzundaki bu kararsız sınıfı tekrar inceleyin:
unstable class Snack {
…
unstable val tags: Set<String>
…
}
Sabit bir koleksiyon kullanarak tags
ürününü kararlı hale getirebilirsiniz. Sınıfta, tags
türünü ImmutableSet<String>
olarak değiştirin:
data class Snack{
…
val tags: ImmutableSet<String> = persistentSetOf()
…
}
Bunu yaptıktan sonra, sınıfın tüm parametreleri sabit kalır ve Compose derleyicisi sınıfı kararlı olarak işaretler.
Stable
veya Immutable
ile ek açıklama ekleyin
Kararlılık sorunlarını çözmenin olası bir yolu, kararsız sınıflara @Stable
veya @Immutable
ile ek açıklama eklemektir.
Bir sınıfa ek açıklama eklemek, derleyicinin normalde sınıfınızla ilgili olarak tahminde bulunacağı şeyi geçersiz kılar. Kotlin'deki !!
operatörüne benzer. Bu ek açıklamaları nasıl kullandığınıza
çok dikkat etmelisiniz. Derleyici davranışını geçersiz kılmak, composable'ınızın beklediğiniz zamanda yeniden oluşturmaması gibi öngörülemeyen hatalara yol açabilir.
Sınıfınızı ek açıklama olmadan kararlı hale getirmek mümkünse bu şekilde istikrarı sağlamaya çalışmalısınız.
Aşağıdaki snippet, sabit olarak ek açıklamaya sahip bir veri sınıfının minimal bir örneğini sunmaktadır:
@Immutable
data class Snack(
…
)
@Immutable
veya @Stable
ek açıklaması kullanmanızdan bağımsız olarak Compose derleyicisi Snack
sınıfını kararlı olarak işaretler.
Koleksiyonlardaki ek açıklamalı sınıflar
List<Snack>
türünde parametre içeren bir composable düşünün:
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
…
unstable snacks: List<Snack>
…
)
Snack
öğesine @Immutable
ek açıklaması ekleseniz bile Compose derleyicisi, HighlightedSnacks
içindeki snacks
parametresini kararsız olarak işaretler.
Parametreler, koleksiyon türleri söz konusu olduğunda sınıflarla aynı sorunla karşılaşır. Compose derleyicisi, List
türündeki bir parametreyi her zaman kararsız olarak işaretler. Bu, kararlı türlerin bir koleksiyonu olsa bile geçerlidir.
Tek bir parametreyi kararlı olarak işaretleyemez veya her zaman atlanabilir olması için bir composable'a ek açıklama ekleyemezsiniz. Bu süreçte birden fazla yol mevcuttur.
Kararsız koleksiyon sorununu çözmenin birkaç yolu vardır. Aşağıdaki alt bölümlerde bu farklı yaklaşımlar özetlenmektedir.
Yapılandırma dosyası
Kod tabanınızdaki kararlılık sözleşmesine bağlı kalmak isterseniz kararlılık yapılandırma dosyanıza kotlin.collections.*
ekleyerek Kotlin koleksiyonlarını kararlı olarak değerlendirebilirsiniz.
Sabit koleksiyon
Sabitliğin derleme zamanı güvenliği için List
yerine bir kotlinx sabit koleksiyonu kullanabilirsiniz.
@Composable
private fun HighlightedSnacks(
…
snacks: ImmutableList<Snack>,
…
)
Wrapper
Sabit bir koleksiyon kullanamıyorsanız, kendi koleksiyonunuzu oluşturabilirsiniz. Bu işlemi yapmak için List
öğesini ek açıklamalı bir kararlı sınıfta sarmalayın. Gereksinimlerinize bağlı olarak bunun için en iyi seçenek büyük olasılıkla genel bir sarmalayıcıdır.
@Immutable
data class SnackCollection(
val snacks: List<Snack>
)
Daha sonra bunu composable'ınızda parametrenin türü olarak kullanabilirsiniz.
@Composable
private fun HighlightedSnacks(
index: Int,
snacks: SnackCollection,
onSnackClick: (Long) -> Unit,
modifier: Modifier = Modifier
)
Çözüm
Bu yaklaşımlardan herhangi birini uyguladıktan sonra Compose derleyicisi artık HighlightedSnacks
Composable'ı hem skippable
hem de restartable
olarak işaretler.
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int
stable snacks: ImmutableList<Snack>
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
)
Yeniden oluşturma sırasında, girişlerinin hiçbiri değiştirilmemişse Compose artık HighlightedSnacks
'i atlayabilir.
Kararlılık yapılandırma dosyası
Compose Derleyici 1.5.5'ten itibaren derleme sırasında kararlı olarak değerlendirilecek sınıfların yapılandırma dosyası sağlanabilir. Bu, LocalDateTime
gibi standart kitaplık sınıfları gibi kontrol etmediğiniz sınıfları kararlı olarak değerlendirmenize olanak tanır.
Yapılandırma dosyası, satır başına bir sınıf içeren bir düz metin dosyasıdır. Yorumlar, tek ve çift joker karakterler desteklenir. Aşağıda örnek bir yapılandırma gösterilmektedir:
// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider kotlin collections stable
kotlin.collections.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>
Bu özelliği etkinleştirmek için yapılandırma dosyasının yolunu Compose derleyici seçeneklerine iletin.
Modern
kotlinOptions {
freeCompilerArgs += [
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
project.absolutePath + "/compose_compiler_config.conf"
]
}
Kotlin
kotlinOptions {
freeCompilerArgs += listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
"${project.absolutePath}/compose_compiler_config.conf"
)
}
Compose derleyicisi projenizdeki her modülde ayrı ayrı çalıştığından, gerekirse farklı modüller için farklı yapılandırmalar sağlayabilirsiniz. Alternatif olarak, projenizin kök düzeyinde bir yapılandırmaya sahip olabilir ve bu yolu her modüle iletebilirsiniz.
Birden çok modül
Yaygın olarak karşılaşılan diğer bir sorun da çok modüllü mimariyle ilgilidir. Compose derleyicisi, bir sınıfın kararlı olup olmadığını belirleyebilmesi için sınıfın başvurduğu tüm temel olmayan türlerin açık bir şekilde kararlı olarak veya Compose derleyicisiyle de oluşturulmuş bir modülde işaretlenmesi gerekir.
Veri katmanınız, önerilen yaklaşım olan kullanıcı arayüzü katmanından ayrı bir modülde bulunuyorsa bu, karşılaştığınız bir sorun olabilir.
Çözüm
Bu sorunu çözmek için aşağıdaki yaklaşımlardan birini uygulayabilirsiniz:
- Sınıfları Derleyici yapılandırma dosyanıza ekleyin.
- Veri katmanı modüllerinizde Compose derleyicisini etkinleştirin veya uygun durumlarda sınıflarınızı
@Stable
ya da@Immutable
ile etiketleyin.- Veri katmanınıza Compose bağımlılığı eklemek buna dahildir. Ancak bu,
Compose-UI
için değil, yalnızca Compose çalışma zamanının bağımlılığıdır.
- Veri katmanınıza Compose bağımlılığı eklemek buna dahildir. Ancak bu,
- Kullanıcı arayüzü modülünüzde, veri katmanı sınıflarınızı kullanıcı arayüzüne özel sarmalayıcı sınıflarına sarmalayın.
Aynı sorun, Composer derleyicisini kullanmayan harici kitaplıklar kullanılırken de ortaya çıkar.
Her composable atlanamaz
Kararlılıkla ilgili sorunları düzeltmeye çalışırken, her composable'ı atlanabilir hâle getirmeye çalışmamalısınız. Bunu yapmaya çalışmak, erken optimizasyona yol açabilir ve bu da, düzelttiğinden çok soruna yol açar.
Atlanabilir olmanın gerçek bir avantaj sağlamadığı ve kodun sürdürülmesinin zor olduğu birçok durum vardır. Örnek:
- Sık sık veya hiç yeniden düzenlenmeyen bir composable.
- Tek başına atlanabilir composable'lar çağıran bir composable.
- Bir composable, çok sayıda parametreye sahip olup pahalı ve eşit uygulamalara sahiptir. Bu durumda, herhangi bir parametrenin değişip değişmediğini kontrol etmenin maliyeti, ucuz bir yeniden düzenleme maliyetinden ağır basabilir.
Bir composable, atlanabilir olduğunda buna değmeyebilecek küçük bir ek yük getirir. Yeniden başlatılabilir olmanın, gereğinden fazla ek yük gerektirdiğini düşündüğünüz durumlarda, composable'ınıza yeniden başlatılamaz olacak şekilde ek açıklama ekleyebilirsiniz.