State ve Jetpack Compose

Bir uygulamadaki durum, zaman içinde değişebilen herhangi bir değerdir. Bu, çok geniş bir yelpazede Oda veritabanından bir değişkene kadar her şeyi sınıfını kullanır.

Tüm Android uygulamaları, kullanıcıya gösterilir. Android'deki durum örnekleri uygulamalar:

  • Ağ bağlantısının kurulamadığı durumlarda gösterilen bir Snackbar.
  • Bir blog yayını ve ilişkili yorumlar.
  • Kullanıcı tıkladığında oynatılan düğmelerde dalga animasyonları.
  • Kullanıcının bir resmin üzerine çizebileceği çıkartmalar.

Jetpack Compose, nerede ve nasıl depoladığınızı ve kullandığınız konusunda açık olmanıza yardımcı olur durumu hakkında bilgi edinin. Bu kılavuz, devlet ile devlet arasındaki composable'ların yanı sıra Jetpack Compose'un sunduğu API'ler hakkında daha fazla bilgi çok kolay.

Durum ve yapı

Oluşturma, bildirim temellidir ve bu nedenle, bunu güncellemenin tek yolu yeni bağımsız değişkenlerle aynı composable'ı oluşturur. Bu argümanlar Kullanıcı arayüzü durumu. Bir durum her güncellendiğinde bir yeniden düzenleme gerçekleştirilir. Kullanıcı Sonuç olarak, TextField gibi öğeler şuralarda olduğu gibi otomatik olarak güncellenmez: zorunlu XML tabanlı görünümlerdir. Bir composable'ın yeni duruma açıkça söylenmesi gerekir güncellemelerini yapmanız gerekir.

@Composable
private fun HelloContent() {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello!",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.bodyMedium
        )
        OutlinedTextField(
            value = "",
            onValueChange = { },
            label = { Text("Name") }
        )
    }
}

Bu komutu çalıştırıp metin girmeye çalışırsanız hiçbir şey olmadığını görürsünüz. İşte bu çünkü TextField kendi kendini güncellemez; value olduğunda güncellenir parametre değişiklikleridir. Bunun nedeni, bestenin ve yeniden bestenin Oluştur'u tıklayın.

İlk beste ve yeniden oluşturma hakkında daha fazla bilgi edinmek için E-posta Yazma Özelliğinde Düşünme.

composable'larda durum

Özelleştirilebilir işlevler remember Nesneleri bellekte depolamak için kullanılan API. remember tarafından hesaplanan bir değer sırasında Beste'de saklanır ve depolanan değer yeniden düzenleme sırasında döndürülür. remember, hem değişken hem de sabit nesneleri depolamak için kullanılabilir.

mutableStateOf gözlemlenebilir MutableState<T>, Bu, oluşturma çalışma zamanıyla entegre gözlemlenebilir bir türdür.

interface MutableState<T> : State<T> {
    override var value: T
}

value uygulamasında yapılan değişiklikler, composable işlevlerin yeniden oluşturulmasını planlar value yazıyor.

Bir composable'da MutableState nesnesini tanımlamanın üç yolu vardır:

  • val mutableState = remember { mutableStateOf(default) }
  • var value by remember { mutableStateOf(default) }
  • val (value, setValue) = remember { mutableStateOf(default) }

Bu beyanlar eşdeğerdir ve farklı devlet kullanımlarından ibarettir. Her bir kampanya için daha kolay okunacak bir kod belirleyin.

by yetki verilmiş kullanıcı söz dizimi için aşağıdaki içe aktarma işlemleri gerekir:

import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

Hatırlanan değeri diğer composable'lar için parametre olarak veya hangi composable'ın görüntüleneceğini değiştirmek için ifadelerde mantık mantığı Örneğin, Ad boşsa karşılama mesajını görüntülemek istemiyorsanız, if ekstresi:

@Composable
fun HelloContent() {
    Column(modifier = Modifier.padding(16.dp)) {
        var name by remember { mutableStateOf("") }
        if (name.isNotEmpty()) {
            Text(
                text = "Hello, $name!",
                modifier = Modifier.padding(bottom = 8.dp),
                style = MaterialTheme.typography.bodyMedium
            )
        }
        OutlinedTextField(
            value = name,
            onValueChange = { name = it },
            label = { Text("Name") }
        )
    }
}

remember, yeniden bestelerde durumu korumanıza yardımcı olur ancak değer, yapılandırma değişiklikleri genelinde korunuyor. Bunun için rememberSaveable rememberSaveable, kaydedilebilecek tüm değerleri otomatik olarak kaydeder. Bundle klasörüne kaydedildi. Diğer değerler için bir özel koruyucu nesnesi aktarabilirsiniz.

Desteklenen diğer eyalet türleri

Oluşturma işlemi, durum muhafazası için MutableState<T> kullanmanızı gerektirmez; o diğer gözlemlenebilir türleri destekler. Başka bir gözlemlenebilir türü okumadan önce Compose'u kullanıyorsanız State<T> composable'ın durum değiştiğinde otomatik olarak yeniden oluşturulur.

Ortak gözlemlenebilir öğelerden State<T> oluşturmak için işlevlerle gemiler oluşturun türleri hakkında daha fazla bilgi edinin. Bu entegrasyonları kullanmadan önce aşağıda özetlendiği şekilde uygun yapıları:

Kotlin

dependencies {
      ...
      implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2")
}

Eski

dependencies {
      ...
      implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.2"
}
  • Flow: collectAsState()

    collectAsState, collectAsStateWithLifecycle ile benzer çünkü aynı zamanda bir Flow öğesinden değerleri toplar ve Oluştur'a State dönüştürür.

    Platformdan bağımsız kod için yerine collectAsState kullanın collectAsStateWithLifecycle: Yalnızca Android'de kullanılabilir.

    collectAsState için ek bağımlılıklara gerek yoktur. compose-runtime içinde mevcut.

  • LiveData: observeAsState()

    observeAsState(), bu LiveData kümesini gözlemlemeye başlar ve değerlerini temsil eder State üzerinden.

    build.gradle dosyasında aşağıdaki bağımlılık zorunludur:

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-livedata:1.6.8")
}

Eski

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-livedata:1.6.8"
}

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-rxjava2:1.6.8")
}

Eski

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-rxjava2:1.6.8"
}

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-rxjava3:1.6.8")
}

Eski

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-rxjava3:1.6.8"
}

Durum bilgili ve durum bilgisiz

Bir nesneyi depolamak için remember kullanan bir composable dahili durum oluşturur, composable'ı durum bilgili hale getirir. HelloContent, durum bilgili bir örnektir. composable, çünkü name durumunu dahili olarak muhafaza ediyor ve değiştiriyor. Bu arayanın, durumu kontrol etmesi gerekmeyen ve ve bu uygulamaları, devleti yönetmek zorunda kalmadan kullanabiliyor. Ancak, dahili durum genellikle daha az yeniden kullanılabilir ve test edilmesi daha zordur.

Durum bilgisiz composable, herhangi bir durumda olmayan bir composable'dır. Kolay bir durum bilgisizi başarmanın bir yolu, durumunuzu kaldırma.

Yeniden kullanılabilir composable'lar geliştirdikçe, genellikle hem durum bilgili ve aynı composable'ın durum bilgisiz sürümünü içerir. Durum bilgili sürüm: devleti önemsemediğini arayanlar için yararlı olduğunun yanı sıra sürümü, devleti kontrol etmesi veya kaldırması gereken arayanlar için gereklidir.

Eyalet kaldırma

Compose'da durum yükseltme, bir composable'ın çağrısını yapan kullanıcıya geçiş durumu kalıbıdır bir composable durum bilgisiz hale getirmektir. Eyalet tırmanmalarındaki genel model Jetpack Compose, durum değişkenini iki parametreyle değiştirmektir:

  • value: T: gösterilecek geçerli değer
  • onValueChange: (T) -> Unit: Değerin değiştirilmesini isteyen bir etkinlik, burada T, önerilen yeni değerdir

Ancak kullanabileceğiniz seçenekler onValueChange ile sınırlı değildir. Daha spesifik etkinlikler composable için uygunsa bunları lambdas kullanarak tanımlamalısınız.

Bu şekilde kaldırılan eyaletin bazı önemli özellikleri vardır:

  • Tek doğru veri kaynağı: Durumu kopyalamak yerine hareket ettirerek tek bir doğruluk kaynağının bulunduğundan emin olun. Bu sayede hatalardan kaçınabilirsiniz.
  • Encapsulated: Yalnızca durum bilgili composable'ların durumlarını değiştirebilir. İnsanların tamamen dahili.
  • Paylaşılabilir: Kaldırılmış durum, birden fazla composable ile paylaşılabilir. Şu durumda: name öğesini farklı bir composable'da okumak istemiştim. Bunu kaldırmak size yapalım.
  • Kesişilebilir: Durum bilgisiz composable'ları arayanlar, veya etkinlikleri yoksayın ya da değiştirin.
  • Ayrıştırıldı: Durum bilgisiz composable'ların durumu depolanabilir elinizin altında. Örneğin, name artık bir ViewModel içine taşınabilir.

Bu örnekte, name ve onValueChange öğelerini HelloContent ve ağaçta yukarı doğru taşıyarak HelloScreen HelloContent numaralı telefonu arar.

@Composable
fun HelloScreen() {
    var name by rememberSaveable { mutableStateOf("") }

    HelloContent(name = name, onNameChange = { name = it })
}

@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello, $name",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.bodyMedium
        )
        OutlinedTextField(value = name, onValueChange = onNameChange, label = { Text("Name") })
    }
}

Eyaleti HelloContent dışına çıkararak ve test edebilirsiniz. HelloContent durumundan ayrıştırılır. Ayrıştırma, bir URL'yi değiştirmeniz veya HelloScreen yerine HelloContent değerini değiştirmeniz gerekmez yardımcı olur.

Durumun düşüp olayların yükseldiği kalıba tek yönlü veri akışı olduğundan emin olun. Bu örnekte, eyalet HelloScreen değerinden düşürülür HelloContent ve etkinlikler HelloContent ile HelloScreen arasında artar. Ölçüt tek yönlü veri akışından sonra, tüm boyutlardaki uygulamanızın durumu depolayan ve değiştiren kısımlarından kullanıcı arayüzünde görebilirsiniz.

Daha fazla bilgi edinmek için Kaldırma durumu sayfasını inceleyin.

Compose'da durum geri yükleniyor

rememberSaveable API, remember ile benzerdir çünkü hem yeniden bestelerde hem de etkinlik veya süreç genelinde durumu korur kaydedilmiş örnek durumu mekanizmasını kullanarak yeniden oluşturma. Örneğin, şöyle bir şeyde Ekran döndürüldüğünde.

Eyalet bilgisini depolamanın yolları

Bundle öğesine eklenen tüm veri türleri otomatik olarak kaydedilir. Şu durumda: Bundle öğesine eklenemeyecek bir öğeyi kaydetmek istiyorsanız, seçenekleri vardır.

Paket haline getir

En basit çözüm, @Parcelize ek açıklama eklemeniz gerekir. Nesne ayrıştırılabilir hale gelir ve paketlenebilir. Örneğin, Bu kod, ayrıştırılabilir bir City veri türü oluşturur ve bunu durumu.

@Parcelize
data class City(val name: String, val country: String) : Parcelable

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

Harita Koruyucu

Herhangi bir nedenle @Parcelize uygun değilse şu işlemler için mapSaver kullanabilirsiniz: bir nesneyi bir değer grubuna dönüştürmek için kullanabileceğiniz Bundle içine kaydedebilirsiniz.

data class City(val name: String, val country: String)

val CitySaver = run {
    val nameKey = "Name"
    val countryKey = "Country"
    mapSaver(
        save = { mapOf(nameKey to it.name, countryKey to it.country) },
        restore = { City(it[nameKey] as String, it[countryKey] as String) }
    )
}

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable(stateSaver = CitySaver) {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

Liste Kaydedeni

Harita için anahtarları tanımlama ihtiyacını ortadan kaldırmak amacıyla listSaver öğesini de kullanabilirsiniz ve dizinlerini anahtar olarak kullanın:

data class City(val name: String, val country: String)

val CitySaver = listSaver<City, Any>(
    save = { listOf(it.name, it.country) },
    restore = { City(it[0] as String, it[1] as String) }
)

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable(stateSaver = CitySaver) {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

Compose'da eyalet sahipleri

Basit durum kaldırma işlemi, composable işlevlerin kendisinden yönetilebilir. Ancak, izlenecek durum miktarı artarsa veya bu durumun composable fonksiyonlar ortaya çıktığında bu fonksiyonlara mantığın ve eyaletin diğer sınıflara olan sorumluluklarını içerir: eyalet sahipleri.

Compose'da durum kaldırma dokümanlarına bakın veya daha genel olarak Daha fazla bilgi edinmek için mimari kılavuzundaki Durum sahipleri ve Kullanıcı Arayüzü Durumu sayfasına bakın.

Tuşlar değiştiğinde hesaplamaları hatırlamayı yeniden tetikle

remember API, MutableState ile birlikte sıklıkla kullanılır:

var name by remember { mutableStateOf("") }

Burada, remember işlevinin kullanılması, MutableState değerinin hayatta kalmasını sağlar çok önemli.

remember genellikle calculation lambda parametresi alır. remember olduğunda çalıştırıldığında calculation lambda'yı çağırır ve sonucunu depolar. Etkinlik sırasında yeniden düzenleme, remember en son depolanan değeri döndürür.

Önbelleğe alma durumunun yanı sıra remember öğesini kullanarak herhangi bir nesneyi veya başlatması pahalı olan bestede yapılan bir işlemin sonucu veya hesaplamanız gerekir. Bu hesaplamayı her yeniden oluşturmada tekrarlamak istemeyebilirsiniz. Bir örnek olarak, pahalı bir ShaderBrush nesnesini oluşturabilirsiniz. işlem:

val brush = remember {
    ShaderBrush(
        BitmapShader(
            ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(),
            Shader.TileMode.REPEAT,
            Shader.TileMode.REPEAT
        )
    )
}

remember, değeri Beste'den ayrılana kadar depolar. Bununla birlikte, geçersiz kılma yönteminden yararlanabilirsiniz. remember API ayrıca bir key veya keys parametresinden yararlanın. Bu tuşlardan herhangi biri değişirse, fonksiyon yeniden oluşturur, remember önbelleği geçersiz kılar ve hesaplamayı yürütür lambda bloğunu tekrar deneyin. Bu mekanizma, bir problemin yaşam döngüsü boyunca temsil eder. Bu hesaplama, giriş yapılana kadar geçerli kalır değiştirebilirsiniz.

Aşağıdaki örneklerde bu mekanizmanın nasıl çalıştığı gösterilmektedir.

Bu snippet'te bir ShaderBrush oluşturulur ve arka plan olarak kullanılır resmi Box composable'ın resmi. remember, ShaderBrush örneğini depolar çünkü daha önce de anlatıldığı gibi yeniden oluşturulması pahalıdır. remember alır key1 parametresi olarak avatarRes kullanılır. Bu, seçilen arka plan resmidir. Eğer avatarRes değişir, fırça yeni resimle yeniden oluşturulur ve şuraya yeniden uygulanır: Box. Bu durum, kullanıcı başka bir resmi arka plan seçin.

@Composable
private fun BackgroundBanner(
    @DrawableRes avatarRes: Int,
    modifier: Modifier = Modifier,
    res: Resources = LocalContext.current.resources
) {
    val brush = remember(key1 = avatarRes) {
        ShaderBrush(
            BitmapShader(
                ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(),
                Shader.TileMode.REPEAT,
                Shader.TileMode.REPEAT
            )
        )
    }

    Box(
        modifier = modifier.background(brush)
    ) {
        /* ... */
    }
}

Sonraki snippet'te durum, düz durum sahip sınıfına çekilir. MyAppState. Bir öğeyi başlatmak için bir rememberMyAppState işlevi sunar. remember kullanılarak sınıfın örneğidir. Aşağıdaki gibi fonksiyonları kullanıma sunarak başarılı bir örneği oluşturmak için Compose'da yaygın olarak kullanılan bir kalıptır. İlgili içeriği oluşturmak için kullanılan rememberMyAppState işlevi windowSizeClass değerini alır ve bu değer remember için key parametresi. Bu parametre değişirse uygulamanın şunları yapması gerekir: düz durum sahip sınıfını en son değerle yeniden oluşturun. Bu, aşağıdaki durumlarda yaşanabilir: Örneğin, kullanıcı cihazı döndürür.

@Composable
private fun rememberMyAppState(
    windowSizeClass: WindowSizeClass
): MyAppState {
    return remember(windowSizeClass) {
        MyAppState(windowSizeClass)
    }
}

@Stable
class MyAppState(
    private val windowSizeClass: WindowSizeClass
) { /* ... */ }

Oluştur, bir anahtarda ve depolanan değeri geçersiz kılar.

Yeniden oluşturmanın ötesinde anahtarlar içeren mağaza durumu

rememberSaveable API, remember çevresinde şunları depolayabilecek bir sarmalayıcıdır verileri Bundle içindedir. Bu API, devletin yalnızca değil, aynı zamanda yeniden oluşturma ve sistem tarafından başlatılan sürecin sonlandırılması gibi unsurlardır. rememberSaveable, aynı amaçla input parametre alır remember keys alıyor. Girişlerden herhangi biri yapıldığında önbellek geçersiz hale gelir değiştirin. İşlev yeniden oluşturulduğunda, rememberSaveable yeniden yürütülür lambda bloğu hesaplaması.

Aşağıdaki örnekte rememberSaveable, userTypedQuery için typedQuery değişiklik:

var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) {
    mutableStateOf(
        TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length))
    )
}

Daha fazla bilgi

State ve Jetpack Compose hakkında daha fazla bilgi edinmek için aşağıdakilere bakın ek kaynaklar.

Örnekler

Codelab'ler

Videolar

Bloglar

ziyaret edin. ziyaret edin.