Bu sayfada, bir composable'ın yaşam döngüsünü ve Compose'un bir composable'ın yeniden kompozisyona ihtiyaç duyup duymadığına nasıl karar verdiğini öğreneceksiniz.
Yaşam döngüsüne genel bakış
Durumu yönetme belgelerinde belirtildiği gibi Beste, uygulamanızın kullanıcı arayüzünü açıklar ve composable'lar çalıştırılarak oluşturulur. Beste, kullanıcı arayüzünüzü tanımlayan 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 Beste içinde açıklamak için çağırdığınız composable'ları takip eder. Ardından, uygulamanızın durumu değiştiğinde Jetpack Composer bir yeniden oluşturma planlar. Yeniden kompozisyon, Jetpack Compose'un durum değişikliklerine göre değişmiş olabilecek composable'ları yeniden çalıştırması ve ardından Beste'yi değişiklikleri yansıtacak şekilde güncellemesidir.
Bir Beste yalnızca bir başlangıç bestesiyle üretilebilir ve yeniden kompozisyon ile güncellenebilir. Bir Besteyi değiştirmenin tek yolu yeniden oluşturmadır.
Şekil 1. Bir composable'ın Bestedeki yaşam döngüsü. Besteye girer, 0 veya daha fazla kez yeniden derlenir ve Beste'den ayrılır.
Yeniden oluşturma genellikle bir
State<T> nesnesinde değişiklik yapıldığında tetiklenir. Compose bunları izler ve Beste içinde bu belirli
State<T> öğesini okuyan tüm composable'lar ile atlanamayan dedikleri composable'ları çalıştırır.
Bir composable birden çok kez çağrılırsa Beste içine birden fazla örnek yerleştirilir. Her çağrının Bestede kendi yaşam döngüsü vardır.
@Composable fun MyComposable() { Column { Text("Hello") Text("World") } }
2. Şekil. Kompozisyonda
MyComposable gösterimi. Bir composable birden çok kez çağrılırsa Beste içine birden fazla örnek yerleştirilir. Farklı renge sahip bir öğe, ayrı bir örnek olduğunu gösterir.
Bestedeki bir composable'ın anatomisi
Beste içindeki bir composable örneği, çağrı sitesi tarafından tanımlanır. Compose derleyicisi her çağrı sitesini ayrı olarak değerlendirir. Birden fazla çağrı sitesinden composable'lar çağrıldığında, composable'ın birden fazla örneği oluşturulur.
Bir composable, bir yeniden bestede önceki besteye göre farklı composable'ları çağırırsa Compose 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.
Her yeniden oluşturma işlemi için yeniden başlatmak yerine başarıyla tamamlamaları için kimliği korumak, yan efektleri composable'la ilişkilendirmek açısından çok önemlidir.
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'ı ve her zaman
LoginInput composable'ı çağırır. Her çağrının, derleyicinin bunu benzersiz bir şekilde tanımlamak için kullanacağı benzersiz bir çağrı sitesi ve kaynak konumu vardır.
3. Şekil. Durum değiştiğinde ve yeniden kompozisyonda
LoginScreen gösterimi. Aynı renk, yeniden oluşturulmadığı anlamına gelir.
LoginInput örneğinin ilk çağrıdan ikincisine çağrılmasına rağmen
LoginInput örneği yeniden oluşturma işlemlerinde korunur. Ayrıca
LoginInput, yeniden oluşturma işleminde değişen herhangi bir parametreye sahip olmadığından
LoginInput çağrısı, Compose tarafından atlanır.
Akıllı yeniden oluşturma işlemlerine yardımcı olmak için ek bilgiler ekleyin
Bir composable'ı birden çok kez çağırdığınızda Beste'ye birden çok kez eklenir. Aynı çağrı sitesinden bir composable'ı birden çok kez çağırırken Compose'da bu composable'a yapılan her bir çağrıyı benzersiz şekilde tanımlayacak herhangi bir bilgi bulunmaz. Bu nedenle, örnekleri farklı tutmak için çağrı sitesine ek olarak yürütme sırası kullanılır. Bu davranış bazen gerekli olan tek şeydir, ancak bazı durumlarda istenmeyen davranışlara 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 içinde farklı tutmak için çağrı sitesine ek olarak yürütme sırasını kullanır. Listenin altına yeni bir
movie eklenirse Compose, listedeki konumları değişmediğinden zaten Beste'de bulunan örnekleri yeniden kullanabilir. Bu nedenle,
movie girişi bu örnekler için aynıdır.
4. Şekil. Listenin altına yeni bir öğe eklendiğinde Bestedeki
MoviesScreen gösterimi. Beste içindeki
MovieOverview composable yeniden kullanılabilir.
MovieOverview içindeki aynı renk, composable'ın yeniden derlenmediği anlamına gelir.
Ancak
movies listesi, listenin üst kısmına veya ortasına eklenerek, öğeler kaldırılır veya yeniden sıralanarak değiştirilirse giriş parametresi listedeki konumu değişen tüm
MovieOverview çağrılarında yeniden oluşturma işlemi yapılır. Örneğin,
MovieOverview bir film resmini yan efekt kullanarak getirirse bu son derece önemlidir. Efekt devam ederken yeniden oluşturma işlemi
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 gösterimi.
MovieOverview composable tekrar 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 aktarılan
movie kimliğine bağlı olduğunu düşünürüz. Film listesini yeniden sıralarsak ideal olarak, her
MovieOverview composable'ı farklı bir film örneğiyle yeniden oluşturmak yerine Beste ağacındaki örnekleri yeniden sıralarız. Compose, çalışma zamanına ağacın belirli bir bölümünü tanımlamak için kullanmak istediğiniz değerleri, yani
key composable'ı bildirmenizi sağlayan bir yöntem sunar.
Bir kod bloğunun, içinde aktarılmış bir veya daha fazla değerle composable anahtara yapılan bir çağrıyla sarmalanmasıyla bu değerler, bestedeki örneği tanımlamak için kullanılmak üzere birleştirilir.
key değerinin global olarak benzersiz olması gerekmez. Yalnızca çağrı sitesindeki composable'ların çağrıları arasında benzersiz olmalıdır. Dolayısıyla bu örnekte her
movie,
movies arasında benzersiz olan bir
key öğesine sahip olmalıdır; bu
key öğesini uygulamanın başka bir yerinde composable ile paylaşması sorun yaratmaz.
@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 için yapılan her bir çağrıyı tanır ve yeniden kullanabilir.
6. Şekil. Listeye yeni bir öğe eklendiğinde Bestedeki
MoviesScreen gösterimi.
MovieOverview composable'ları benzersiz anahtarlara sahip olduğundan Compose hangi
MovieOverview örneklerinin değişmediğini algılar ve bunları yeniden kullanabilir. Bu nedenle, bu örneklerin yan etkileri çalışmaya devam eder.
Bazı composable'lar
key composable için yerleşik desteğe sahiptir. Örneğin
LazyColumn,
items DSL'sinde ö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
Girişleri önceki besteye göre değişmediği takdirde, yeniden oluşturma sırasında bazı uygun composable işlevlerin yürütmeleri tamamen atlanabilir.
composable işlevler aşağıdaki durumlar dışında atlanabilir:
- İşlev
Unitdışında bir döndürme türüne sahip
- İşleve
@NonRestartableComposableveya
@NonSkippableComposableile not eklenir
- Zorunlu bir parametre, kararlı olmayan türde
Son gereksinimi 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
equalssonucu, aynı iki örnek için her zaman aynı olur.
- Türün herkese açık mülkü değişirse Beste bildirilir.
- Tüm herkese açık mülk türleri de stabildir.
Bu sözleşme kapsamında,
@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 vardır:
- Tüm temel değer türleri:
Boolean,
Int,
Long,
Float,
Charvb.
- Yaylı Çalgılar
- Tüm işlev türleri (lambda)
Bu türlerin tümü, sabit olduğu için istikrar sözleşmesine uygun olabilir. Sabit türler hiçbir zaman değişmediği için hiçbir zaman değişikliği Bileşim'e bildirmeleri gerekmez; bu nedenle bu sözleşmeyi uygulamak çok daha kolaydır.
Kararlı olan ancak değişken olan önemli türlerden biri, Compose'un
MutableState türüdür.
MutableState içinde bir değer tutulursa Compose
State öğesinin
.value özelliğinde yapılan değişiklikler bildirileceğinden durum nesnesinin genel olarak kararlı olduğu kabul edilir.
Bir composable'a parametre olarak geçirilen tüm türler kararlı olduğunda parametre değerleri, kullanıcı arayüzü ağacındaki composable konuma dayalı olarak eşitlik için karşılaştırılır. Bir önceki çağrıdan bu yana tüm değerler değişmediyse yeniden oluşturma atlanır.
Compose, yalnızca kanıtlanabilen türleri kararlı olarak kabul eder. Örneğin, bir arayüz genellikle kararlı değil olarak kabul edilir. Ayrıca, uygulaması sabit olabilecek herkese açık ve değişken özelliklere sahip türler de kararlı değildir.
Compose bir türün kararlı olduğu sonucuna varamıyorsa ancak Composer'ı kararlı olarak değerlendirilmeye zorlamak istiyorsanız bu türü
@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ü normalde sabit olarak kabul edebilir.
@Stable ek açıklamasını ekleyerek Compose'a bu türün kararlı olduğunu ve böylece Compose'un akıllı yeniden derlemeleri desteklediğini belirtmiş olursunuz. Bu aynı zamanda, parametre türü arayüz olarak kullanılıyorsa Compose'un tüm uygulamalarını kararlı olarak değerlendireceği anlamına da gelir.
Sizin için önerilenler
- Not: Bağlantı metni JavaScript kapalıyken görüntülenir
- State ve Jetpack Compose
- Compose'daki yan etkiler
- Oluşturma penceresinde kullanıcı arayüzü durumunu kaydetme