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
Unit
dışında bir döndürme türüne sahip - İşleve
@NonRestartableComposable
veya@NonSkippableComposable
ile 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
equals
sonucu, 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
,Char
vb. - 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