Bu sayfada, bir composable'ın yaşam döngüsü hakkında bilgi edinecek ve Compose'un composable'ın yeniden bestelemeye ihtiyacı olup olmadığına nasıl karar verdiğini öğreneceksiniz.
Yaşam döngüsüne genel bakış
Yönetim durumu dokümanlarında belirtildiği gibi, beste, uygulamanızın kullanıcı arayüzünü açıklar ve composable'ların çalıştırılmasıyla üretilir. Beste, kullanıcı arayüzünüzü açıklayan composable'ların ağaç yapısıdır.
Jetpack Compose, composable'larınızı ilk kez çalıştırdığında ilk beste sırasında kullanıcı arayüzünüzü bir Bestede açıklamak için çağırdığınız composable'ları takip eder. Ardından, uygulamanızın durumu değiştiğinde Jetpack Compose bir yeniden düzenleme planlar. Yeniden düzenleme, Jetpack Compose'un durum değişikliklerine yanıt olarak değişmiş olabilecek composable'ları yeniden yürütmesi ve ardından besteyi değişiklikleri yansıtacak şekilde güncellemesidir.
Bir Beste, yalnızca başlangıçtaki bir besteyle üretilebilir ve yeniden besteleme yoluyla güncellenebilir. Bir besteyi değiştirmenin tek yolu yeniden bestelemektir.
Şekil 1. Bestedeki bir composable'ın yaşam döngüsü. Besteye girer, 0 veya daha fazla kez yeniden yazılır ve Beste'den çıkar.
Yeniden oluşturma, genellikle bir State<T>
nesnesinde yapılan değişiklik nedeniyle tetiklenir. Compose bunları izler ve Beste'deki söz konusu State<T>
öğesini okuyan tüm composable'ları ve çağrılan ve atlanamayan tüm composable'ları çalıştırır.
Bir composable birden fazla kez çağrılırsa Beste'ye birden fazla örnek yerleştirilir. Bestede her çağrının kendi yaşam döngüsü vardır.
@Composable fun MyComposable() { Column { Text("Hello") Text("World") } }
Şekil 2. Bestedeki MyComposable
temsili. Bir composable birden fazla kez çağrılırsa Beste'ye birden fazla örnek yerleştirilir. Farklı renge sahip bir öğe, ayrı bir örnek olduğunu gösterir.
Bestede bir composable'ın anatomisi
Bestedeki bir composable, çağrı sitesi tarafından tanımlanır. Compose derleyicisi her çağrı sitesini ayrı olarak değerlendirir. Birden fazla çağrı sitesinden composable'ın çağrılması, Beste'de birden fazla composable örneği oluşturur.
Yeniden düzenleme sırasında bir composable, önceki bestede olduğundan farklı composable'lar çağırırsa hangi composable'ların çağrıldığını veya çağrılmadığını belirler, her iki bestede de çağrılan composable'lar için Compose girişleri değişmediyse bunları yeniden oluşturmaktan kaçınır.
Yan etkileri composable ile ilişkilendirmek için kimliğin korunması çok önemlidir. Böylece her yeniden oluşturmada yeniden başlatmak yerine başarıyla tamamlanabilirler.
Aşağıdaki örneği inceleyin:
@Composable fun LoginScreen(showError: Boolean) { if (showError) { LoginError() } LoginInput() // This call site affects where LoginInput is placed in Composition } @Composable fun LoginInput() { /* ... */ } @Composable fun LoginError() { /* ... */ }
Yukarıdaki kod snippet'inde LoginScreen
, koşullu olarak LoginError
composable'ı çağırır ve her zaman LoginInput
composable'ı çağırır. Her çağrının benzersiz bir çağrı sitesi ve kaynak konumu vardır. Derleyici, bu bilgileri benzersiz bir şekilde tanımlamak için kullanır.
Şekil 3. Durum değiştiğinde ve bir yeniden oluşturma gerçekleştiğinde bestede LoginScreen
temsili. Aynı renk yeniden düzenlenmediği anlamına gelir.
LoginInput
ilk çağrılmadan ikinci çağrılmaya geçse de LoginInput
örneği yeniden oluşturmalarda korunacaktır. Ayrıca, LoginInput
yeniden oluşturma genelinde değişmiş herhangi bir parametreye sahip olmadığı için LoginInput
çağrısı, Compose tarafından atlanır.
Akıllı yeniden bestelemeye yardımcı olmak için ek bilgi ekleyin
Bir composable'ı birden fazla kez çağırmak, onu Beste'ye de birden çok kez ekler. Bir composable, aynı çağrı sitesinden birden fazla kez çağrıldığında, Compose'un bu composable'a yapılan çağrıları benzersiz bir şekilde tanımlayacak herhangi bir bilgisi olmaz. Bu nedenle, örnekleri ayrı tutmak için çağrı sitesine ek olarak yürütme sırası kullanılır. Bazen gereken tek şey bu davranış olsa da bazı durumlarda istenmeyen davranışa neden olabilir.
@Composable fun MoviesScreen(movies: List<Movie>) { Column { for (movie in movies) { // MovieOverview composables are placed in Composition given its // index position in the for loop MovieOverview(movie) } } }
Yukarıdaki örnekte Compose, örneği Beste'de farklı tutmak için çağrı sitesine ek olarak yürütme sırasını da kullanır. Listenin en altına yeni bir movie
eklenirse Compose, Beste'de yer alan örnekleri yeniden kullanabilir. Bunun nedeni, bu örneklerin listedeki konumları değişmemiş olmasıdır. Bu nedenle, movie
girişi bu örnekler için aynıdır.
4.Şekil Listenin sonuna yeni bir öğe eklendiğinde Bestedeki MoviesScreen
temsili. Bestedeki MovieOverview
composable
yeniden kullanılabilir. MovieOverview
öğesindeki aynı renk, composable'ın
yeniden düzenlenmediği anlamına gelir.
Bununla birlikte, movies
listesi, listenin en üstüne veya ortasına eklenerek, öğeler kaldırılarak veya yeniden sıralanarak değişirse giriş parametresinin listedeki konumu değişen tüm MovieOverview
çağrılarında yeniden oluşturma işlemi gerçekleşir. Örneğin, MovieOverview
yan efekt kullanarak film
görüntüsü getirirse bu son derece önemlidir. Efekt devam ederken yeniden oluşturma
gerçekleşirse işlem iptal edilir ve tekrar başlar.
@Composable fun MovieOverview(movie: Movie) { Column { // Side effect explained later in the docs. If MovieOverview // recomposes, while fetching the image is in progress, // it is cancelled and restarted. val image = loadNetworkImage(movie.url) MovieHeader(image) /* ... */ } }
5. Şekil. Listeye yeni bir öğe eklendiğinde Bestedeki MoviesScreen
temsili. MovieOverview
composable yeniden kullanılamaz ve tüm
yan efektler yeniden başlatılır. MovieOverview
öğesinde farklı bir renk, composable'ın
yeniden derlendiği anlamına gelir.
İdeal olarak MovieOverview
örneğinin kimliğinin, kendisine geçirilen movie
öğesinin kimliğine bağlı olduğunu düşünmek istiyoruz. Film listesini yeniden sıraladığımızda, ideal olarak her MovieOverview
composable'ı farklı bir film örneğiyle yeniden oluşturmak yerine Beste ağacında örnekleri yeniden sıralarız. Compose, çalışma zamanına ağacın belirli bir bölümünü tanımlamak için hangi değerleri kullanmak istediğinizi söylemenizi sağlayan bir yöntem sunar: key
composable.
Bir kod bloku, composable'a bir veya daha fazla değer iletilmiş anahtara yapılan bir çağrıyla sarmalandığında bu değerler, bestede o örneği tanımlamak için kullanılmak üzere birleştirilir. key
değerinin global olarak benzersiz olması gerekmez. Bunun yalnızca çağrı sitesindeki composable'ların çağrıları arasında benzersiz olması gerekir. Dolayısıyla bu örnekte her movie
, movies
içinde benzersiz bir key
özelliğine sahip olmalıdır. Bu key
öğesini uygulamanın başka bir yerinde composable'la paylaşsa da olur.
@Composable fun MoviesScreenWithKey(movies: List<Movie>) { Column { for (movie in movies) { key(movie.id) { // Unique ID for this movie MovieOverview(movie) } } } }
Yukarıdaki koşullarda, listedeki öğeler değişse bile Compose, MovieOverview
çağrılarını ayrı ayrı tanır ve yeniden kullanabilir.
6. Şekil. Listeye yeni bir öğe eklendiğinde Bestedeki MoviesScreen
temsili. MovieOverview
composable'ın benzersiz anahtarları olduğundan Compose, hangi MovieOverview
örneklerinin değişmediğini tespit edip bunları yeniden kullanabilir. Bunların yan etkileri devam eder.
Bazı composable'lar yerleşik key
composable desteğine sahiptir. Örneğin, LazyColumn
, items
DSL'de özel bir key
belirtmeyi kabul eder.
@Composable fun MoviesScreenLazy(movies: List<Movie>) { LazyColumn { items(movies, key = { movie -> movie.id }) { movie -> MovieOverview(movie) } } }
Girişler değişmediyse atlama
Yeniden oluşturma sırasında, girişleri önceki besteye göre değişmediyse bazı uygun composable işlevlerin yürütme işlemleri tamamen atlanabilir.
Bir composable işlev, aşağıdaki durumlar haricinde atlanmaya uygundur:
- İşlev,
Unit
dışında bir dönüş türü içeriyor - İşlev,
@NonRestartableComposable
veya@NonSkippableComposable
ile ek açıklamalara sahip - Gerekli parametrelerden biri kararsız türde
Son şartı hafifleten deneysel bir derleyici modu olan Güçlü Atlama vardır.
Bir türün kararlı olarak kabul edilmesi için aşağıdaki sözleşmeye uygun olması gerekir:
- İki örnek için
equals
sonucu, aynı iki örnek için tamamen aynı olur. - Türün herkese açık bir mülkü değişirse Beste bilgilendirilir.
- Tüm kamu mülkü türleri de sabittir.
@Stable
ek açıklaması kullanılarak açıkça kararlı olarak işaretlenmeseler bile, Compose derleyicisinin kararlı olarak değerlendireceği bazı önemli yaygın türler bu sözleşme kapsamına girer:
- Tüm temel değer türleri:
Boolean
,Int
,Long
,Float
,Char
vb. - Yaylı Çalgılar
- Tüm işlev türleri (lambdas)
Bu türlerin tümü, sabit oldukları için istikrarlı sözleşmeye uygundur. Sabit türler hiçbir zaman değişmediğinden, değişikliğin bileşimini hiçbir zaman bildirmek zorunda kalmazlar. Dolayısıyla, bu sözleşmeye uymak çok daha kolaydır.
Kararlı ancak değişebilir olan önemli bir tür, Compose'un MutableState
türüdür. Bir değer MutableState
öğesinde tutulursa genel durum nesnesinin kararlı olduğu kabul edilir. Çünkü Compose, State
öğesinin .value
özelliğinde değişiklik yapıldığında bilgilendirilir.
Bir composable'a parametre olarak iletilen tüm türler kararlı olduğunda parametre değerleri, kullanıcı arayüzü ağacındaki composable konuma göre eşitlik açısından karşılaştırılır. Önceki çağrıdan bu yana tüm değerler değişmediyse yeniden oluşturma işlemi atlanır.
Compose, bir türü kanıtlayabildiği takdirde kararlı olarak kabul eder. Örneğin, bir arayüz genellikle kararlı değildir ve uygulanması sabit olabilen, değişken herkese açık özelliklere sahip türler de kararlı değildir.
Compose bir türün kararlı olduğunu belirleyemiyorsa ancak Compose'u kararlı olarak ele almaya zorlamak istiyorsanız @Stable
ek açıklamasıyla işaretleyin.
// Marking the type as stable to favor skipping and smart recompositions. @Stable interface UiState<T : Result<T>> { val value: T? val exception: Throwable? val hasError: Boolean get() = exception != null }
Yukarıdaki kod snippet'inde UiState
bir arayüz olduğundan, Compose bu türün kararlı olmadığını belirtebilir. @Stable
ek açıklaması ekleyerek, Compose'a bu türün kararlı olduğunu bildirerek Compose'un akıllı yeniden bestelere öncelik vermesini sağlarsınız. Bu aynı zamanda, arayüzün parametre türü olarak kullanılması durumunda Compose'un tüm uygulamalarını kararlı olarak değerlendireceği anlamına da gelir.
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir
- State ve Jetpack Compose
- Compose'da yan etkiler
- Oluşturma'da kullanıcı arayüzü durumunu kaydet