Bu sayfada, composable'ların yaşam döngüsü ve Compose'un bir composable'ın yeniden oluşturulması gerekip gerekmediğine nasıl karar verdiği hakkında bilgi edineceksiniz.
Yaşam döngüsüne genel bakış
Durumu yönetme dokümanlarında belirtildiği gibi, bir kompozisyon, uygulamanızın kullanıcı arayüzünü tanımlar ve composable'lar çalıştırılarak oluşturulur. Kompozisyon, kullanıcı arayüzünüzü tanımlayan composable'ların ağaç yapısıdır.
Jetpack Compose, ilk kompozisyon sırasında composable'larınızı ilk kez çalıştırdığında, kullanıcı arayüzünüzü bir kompozisyonda tanımlamak için çağırdığınız composable'ları takip eder. Ardından, uygulamanızın durumu değiştiğinde Jetpack Compose bir yeniden oluşturma planlar. Yeniden oluşturma, Jetpack Compose'un durum değişikliklerine yanıt olarak değişmiş olabilecek composable'ları yeniden yürütmesi ve ardından değişiklikleri yansıtmak için Composition'ı güncellemesidir.
Bir beste yalnızca ilk beste ile oluşturulabilir ve yeniden beste yapılarak güncellenebilir. Bir Kompozisyonu değiştirmenin tek yolu yeniden kompozisyondur.
Yeniden oluşturma genellikle bir State<T> nesnesinde yapılan bir değişiklikle tetiklenir. Compose, bunları izler ve kompozisyonda bu belirli State<T> değerini okuyan tüm composable'ları ve bu composable'ların çağırdığı, atlanamayan tüm composable'ları çalıştırır.
Bir composable birden çok kez çağrılırsa Composition'a birden çok örnek yerleştirilir. Her görüşmenin beste içinde kendi yaşam döngüsü vardır.
@Composable fun MyComposable() { Column { Text("Hello") Text("World") } }
MyComposable öğesinin temsili. Bir composable birden fazla kez çağrılırsa Composition'a birden fazla örnek yerleştirilir. Farklı renkteki bir öğe, ayrı bir örnek olduğunu gösterir.Composition'da composable'ın anatomisi
Composition'daki bir composable örneği, çağrı sitesi ile tanımlanır. Compose derleyicisi, her çağrı sitesini ayrı olarak değerlendirir. Birden fazla çağrı sitesinden composable işlevleri çağırmak, Composition'da composable işlevlerin birden fazla örneğini oluşturur.
Yeniden oluşturma sırasında bir composable, önceki oluşturma sırasında çağırdığından farklı composable'lar çağırırsa Compose, hangi composable'ların çağrıldığını veya çağrılmadığını belirler. Her iki oluşturmada da çağrılan composable'lar için Compose, girişleri değişmediyse bunları yeniden oluşturmaktan kaçınır.
Yan etkilerin bestelenebilir öğeleriyle ilişkilendirilmesi için kimliğin korunması çok önemlidir. Böylece yan etkiler, her yeniden oluşturma işleminde yeniden başlatılmak yerine başarılı bir şekilde tamamlanabilir.
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, LoginError composable'ını koşullu olarak çağırır ve LoginInput composable'ını her zaman çağırır. Her çağrının, derleyicinin benzersiz şekilde tanımlamak için kullanacağı benzersiz bir çağrı sitesi ve kaynak konumu vardır.
LoginScreen öğesinin Kompozisyon'daki temsili. Aynı renk, yeniden oluşturulmadığı anlamına gelir.LoginInput önce çağrılmaktan sonra çağrılmaya geçse de LoginInput örneği yeniden oluşturma işlemlerinde korunur. Ayrıca, LoginInput, yeniden oluşturma sırasında değişen herhangi bir parametreye sahip olmadığından LoginInput çağrısı Compose tarafından atlanır.
Akıllı yeniden oluşturma özelliğine yardımcı olmak için ek bilgiler ekleme
Bir composable'ı birden çok kez çağırmak, onu Composition'a da birden çok kez ekler. Aynı çağrı sitesinden bir composable birden çok kez çağrıldığında Compose, bu composable'a yapılan her çağrıyı benzersiz şekilde tanımlayacak bilgilere sahip olmadığından örnekleri ayrı tutmak için çağrı sitesine ek olarak yürütme sırası kullanılır. Bu davranış bazen yeterli olsa da 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, örneklerin Composition'da farklı kalmasını sağlamak için çağrı sitesine ek olarak yürütme sırasını kullanır. Listenin alt kısmına yeni bir movie eklenirse Compose, listedeki konumları değişmediği için Kompozisyon'da zaten bulunan örnekleri yeniden kullanabilir. Bu nedenle, bu örnekler için movie girişi aynıdır.
MoviesScreen öğesinin gösterimi. Composition'daki MovieOverview composable'ları yeniden kullanabilirsiniz. MovieOverview içindeki aynı renk, composable'ın yeniden oluşturulmadığı anlamına gelir.Ancak movies listesi, listenin üst veya ortasına öğe eklenerek, öğeler kaldırılarak ya da yeniden sıralanarak değişirse giriş parametresinin listedeki konumu değişen tüm MovieOverview çağrılarında yeniden oluşturmaya neden olur. Örneğin, MovieOverview, yan etki kullanarak bir film resmi getiriyorsa bu durum son derece önemlidir. Efekt devam ederken yeniden oluşturma işlemi gerçekleşirse bu işlem iptal edilir ve yeniden başlatılır.
@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) /* ... */ } }
MoviesScreen öğesinin gösterimi. MovieOverview composables yeniden kullanılamaz ve tüm yan etkiler yeniden başlar. MovieOverview içinde farklı bir renk, birleştirilebilir öğenin yeniden oluşturulduğu anlamına gelir.İdeal olarak, MovieOverview örneğinin kimliğinin, kendisine iletilen movie kimliğine bağlı olduğunu düşünmek isteriz. Film listesini yeniden sıralarsak her MovieOverview composable'ı farklı bir film örneğiyle yeniden oluşturmak yerine, ideal olarak Composition ağacındaki örnekleri de benzer şekilde 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ğlar: key composable'ı.
Bir kod bloğunu, bir veya daha fazla değerin iletildiği anahtar composable'ı ile sarmalayarak bu değerleri birleştirip kompozisyondaki örneği tanımlamak için kullanabilirsiniz. key değeri global olarak benzersiz olmak zorunda değildir. Yalnızca çağrı sitesindeki composable'ların çağrıları arasında benzersiz olması gerekir. Dolayısıyla bu örnekte her movie, movies arasında benzersiz olan bir key'ye sahip olmalıdır. Bu key'yi uygulamadaki başka bir composable ile paylaşması sorun değildir.
@Composable fun MoviesScreenWithKey(movies: List<Movie>) { Column { for (movie in movies) { key(movie.id) { // Unique ID for this movie MovieOverview(movie) } } } }
Yukarıdaki bilgiler ışığında, listedeki öğeler değişse bile Compose, MovieOverview için yapılan ayrı ayrı çağrıları tanır ve bunları yeniden kullanabilir.
MoviesScreen öğesinin gösterimi. MovieOverview composable'ların benzersiz anahtarları olduğundan Compose, hangi MovieOverview örneklerinin değişmediğini tanır ve bunları yeniden kullanabilir. Yan etkileri yürütülmeye devam eder.Bazı composable'lar, key composable'ı için yerleşik destek sunar. Örneğin, LazyColumn, items DSL'sinde özel bir key belirtilmesini 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 oluşturma işlemine göre değişmemişse uygun olan bazı composable işlevlerin yürütülmesi tamamen atlanabilir.
Bir composable işlev, aşağıdaki durumlar hariç atlanmaya uygundur:
- İşlevin
Unitolmayan bir dönüş türü var. - İşlev,
@NonRestartableComposableveya@NonSkippableComposableile açıklama eklenmiş - Gerekli bir parametre kararsız bir türde
Son koşulu gevşeten deneysel bir derleyici modu olan Strong Skipping mevcuttur.
Bir türün kararlı olarak kabul edilebilmesi için aşağıdaki sözleşmeye uyması gerekir:
- İki örnek için
equalssonucu, aynı iki örnek için her zaman aynı olacaktır. - Türün herkese açık bir özelliği değişirse Composition bilgilendirilir.
- Tüm genel mülk türleri de kararlıdır.
Bu sözleşmeye dahil olan ve @Stable ek açıklaması kullanılarak açıkça kararlı olarak işaretlenmemiş olsa da Compose derleyicisinin kararlı olarak değerlendireceği bazı önemli ortak 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'lar)
Bu türlerin tümü değişmez oldukları için kararlılık sözleşmesine uyabilir. Değişmez türler asla değişmediğinden, değişikliğin bileşimini asla bildirmeleri gerekmez. Bu nedenle, bu sözleşmeye uymak çok daha kolaydır.
Sabit ancak değiştirilebilir olan önemli bir tür, Compose'un MutableState türüdür. Bir değer MutableState içinde tutuluyorsa Compose, State öğesinin .value özelliğindeki değişikliklerden haberdar edileceğinden genel olarak durum nesnesinin kararlı olduğu kabul edilir.
Bir composable'a parametre olarak iletilen tüm türler kararlı olduğunda, parametre değerleri, kullanıcı arayüzü ağacındaki composable konumuna 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 atlanır.
Compose, bir türün kararlı olduğunu yalnızca kanıtlayabildiği takdirde kabul eder. Örneğin, bir arayüz genellikle kararlı olarak kabul edilmez ve uygulaması değişmez olabilecek, değişebilir genel özelliklere sahip türler de kararlı değildir.
Compose, bir türün kararlı olduğunu çıkaramıyorsa ancak Compose'un bunu kararlı olarak ele almasını zorlamak istiyorsanız 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, normalde bu türü kararsız olarak değerlendirebilir. @Stable
Ek açıklamasını ekleyerek Compose'a bu türün kararlı olduğunu bildirirsiniz. Böylece Compose, akıllı yeniden oluşturmaları tercih edebilir. Bu, arayüz parametre türü olarak kullanılıyorsa 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
- Compose'da kullanıcı arayüzü durumunu kaydetme