Kullanıcı arayüzü durumunu Compose'da kaydet

Eyaletinizin nereye tırmanıldığına ve gerekli mantığa bağlı olarak, kullanıcı arayüzü durumunuzu depolamak ve geri yüklemek için farklı API'ler kullanabilir. Her uygulama bir API kombinasyonundan yararlanmanız gerekir.

Etkinlik veya işlem nedeniyle tüm Android uygulamaları kullanıcı arayüzü durumunu kaybedebilir rekreasyon. Bu durum kaybı aşağıdaki olaylardan kaynaklanabilir:

ziyaret edin.

Pozitif kullanıcılar için, bu olaylardan sonra durumu korumak büyük önem taşır. sahip olacaksınız. Hangi durumun kalıcı olacağını seçmek, uygulamanızın benzersiz kullanıcısına bağlıdır akış gösterir. En iyi uygulama olarak en azından kullanıcı girişini korumalı ve gezinmeyle ilgili durumu gösterir. Örneğin, bir kullanıcının hakkında daha fazla bilgi istediği öğenin kimliği, devam etmekte olan kullanıcı tercihlerini belirleme veya metin alanlarına giriş yapma.

Bu sayfada, kullanıcı arayüzü durumunun nereye bağlı olduğuna bağlı olarak depolanabilecek API'ler ve bunu gerektiren mantığa göre hareket etmeniz gerekir.

Kullanıcı arayüzü mantığı

Durumunuz kullanıcı arayüzüne composable işlevlerde veya yalın Beste'ye dahil edilen durum sahibi sınıfları için Etkinlik ve yeniden oluşturma işlemleri genelinde durumu korumak için rememberSaveable.

Aşağıdaki snippet'te rememberSaveable tek bir boole değerini depolamak için kullanılır Kullanıcı arayüzü öğesi durumu:

@Composable
fun ChatBubble(
    message: Message
) {
    var showDetails by rememberSaveable { mutableStateOf(false) }

    ClickableText(
        text = AnnotatedString(message.content),
        onClick = { showDetails = !showDetails }
    )

    if (showDetails) {
        Text(message.timestamp)
    }
}

Şekil 1. Sohbet mesajı balonuna dokunulduğunda genişleyip daralır.

showDetails, sohbet balonu daraltıldığında depolayan bir boole değişkenidir veya genişletildi.

rememberSaveable, kullanıcı arayüzü öğesi durumunuBundle kaydedilen örnek durumu mekanizmasını ifade eder.

Temel türleri pakete otomatik olarak depolayabilir. Bulunduğunuz eyalet veri sınıfı gibi temel olmayan bir türde tutulursa, Parcelize ek açıklamasını kullanma gibi farklı depolama mekanizmaları listSaver ve mapSaver gibi Compose API'leri kullanarak veya Oluşturma çalışma zamanı Saver sınıfını genişleten özel tasarruf sınıfı. Bkz. Yollar mağaza durumu dokümanlarını inceleyin.

Aşağıdaki snippet'te rememberLazyListState Oluştur Bir reklam öğesinin kaydırma durumundan oluşan LazyListState API depoları LazyColumn veya LazyRow, rememberSaveable kullanarak. Bir LazyListState.Saver adlı özel koruyucu şunları yapabilir: saklamayı ve kaydırma durumunu geri yüklemeyi sağlar. Bir etkinlikten ya da yeniden değerlendirme sürecinden sonra (örneğin, cihaz yönünü değiştirme gibi bir yapılandırma değişikliğinden sonra, korunduğundan emin olun.

@Composable
fun rememberLazyListState(
    initialFirstVisibleItemIndex: Int = 0,
    initialFirstVisibleItemScrollOffset: Int = 0
): LazyListState {
    return rememberSaveable(saver = LazyListState.Saver) {
        LazyListState(
            initialFirstVisibleItemIndex, initialFirstVisibleItemScrollOffset
        )
    }
}

En iyi uygulama

rememberSaveable, kullanıcı arayüzü durumunu depolamak için bir Bundle kullanır. Bu durum aynı zamanda veri yazan diğer API'ler (örneğin, onSaveInstanceState() yararlı olabilir. Ancak, bu Bundle cihazın boyutu sınırlıdır ve bu öğe için nesneleri çalışma zamanında TransactionTooLarge istisnaya neden olabilir. Bu özellikle, aynı öğenin tek bir Activity uygulamasında da Bundle uygulama genelinde kullanılıyor.

Bu tür kilitlenmeleri önlemek için büyük boyutlu karmaşık nesneleri veya listesidir.

Bunun yerine, gerekli olan minimum durumu (kimlikler veya anahtarlar gibi) depolayın ve bunları kullanarak kalıcı kullanıcı arayüzü gibi diğer mekanizmalara geri yükleme yetkisi depolama alanı.

Bu tasarım seçimleri uygulamanızın belirli kullanım alanlarına ve uygulamanızın nasıl davranmasını bekliyorlar?

Eyalet geri yükleme işlemini doğrulayın

rememberSaveable ile depolanan durumun Etkinlik veya işlem şu durumlarda olduğunda öğe oluşturma öğeleri doğru şekilde geri yüklenir: yeniden oluşturulmuş. Bunu başarmak için kullanılabilecek bazı API'ler vardır: StateRestorationTester. Aşağıdakileri yapmak için Test dokümanlarını inceleyin: daha fazla bilgi edinin.

İş mantığı

Kullanıcı arayüzü öğesi durumunuz,ViewModel iş mantığının gerektirdiği şekilde ViewModel API'lerini kullanabilirsiniz.

Android uygulamanızda ViewModel kullanmanın temel avantajlarından biri Google Analytics 4'te tarama yapar. Bir yapılandırma olduğunda etkinlik kaldırılır ve yeniden oluşturulursa, kullanıcı arayüzü durumu ViewModel bellekte tutulur. Etkinlikten sonra eski ViewModel ekli olduğundan emin olun.

Ancak ViewModel örneği, sistem tarafından başlatılan işlem ölümünden sonra da devam edemez. Kullanıcı arayüzü durumunun hayatta kalması için ViewModel, SavedStateHandle API'yi içerir.

En iyi uygulama

SavedStateHandle, kullanıcı arayüzü durumunu depolamak için Bundle mekanizmasını da kullanır. Bu nedenle, bunu yalnızca basit kullanıcı arayüzü öğesi durumunu depolamak için kullanmalısınız.

İş kurallarının uygulanması ve erişilmesiyle oluşturulan ekran kullanıcı arayüzü durumu uygulamanızın kullanıcı arayüzü dışındaki katmanlarının Olası karmaşıklığı ve boyutu nedeniyle SavedStateHandle. Tekliflerinizi otomatikleştirmek ve optimize etmek için karmaşık veya büyük verileri depolamak için farklı mekanizmalar (ör. yerel kalıcı depolama alanı. Süreç yeniden oluşturma işleminden sonra ekran, SavedStateHandle içinde depolanan, geri yüklenen geçici durumu (varsa) ve ekran kullanıcı arayüzü durumu, veri katmanından tekrar oluşturulur.

SavedStateHandle API

SavedStateHandle, kullanıcı arayüzü öğesi durumunu depolamak için farklı API'lere sahiptir. Çoğu son derece önemli:

Oluştur State saveable()
StateFlow getStateFlow()

Oluştur: State

Kullanıcı arayüzü öğesini okumak ve yazmak için SavedStateHandle ürününün saveable API'sini kullanın MutableState olarak görünür, böylece etkinlikten çıkar ve yeniden oluşturma işlemini çok az kod kurulumu gerekir.

saveable API, kullanıma hazır temel türleri destekler ve rememberSaveable() gibi özel koruyucular kullanmak için stateSaver parametresini kullanın.

Aşağıdaki snippet'te message, kullanıcı girişi türlerini bir TextField:

class ConversationViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    var message by savedStateHandle.saveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue(""))
    }
        private set

    fun update(newMessage: TextFieldValue) {
        message = newMessage
    }

    /*...*/
}

val viewModel = ConversationViewModel(SavedStateHandle())

@Composable
fun UserInput(/*...*/) {
    TextField(
        value = viewModel.message,
        onValueChange = { viewModel.update(it) }
    )
}

Aşağıdakiler hakkında daha fazla bilgi için SavedStateHandle dokümanlarına bakın: (saveable API'yi kullanarak) hakkında daha fazla bilgi edinin.

StateFlow

Kullanıcı arayüzü öğesi durumunu depolamak ve bir akış olarak kullanmak için getStateFlow() kullanın SavedStateHandle. StateFlow okundu ve API yalnızca bir anahtar belirtmenizi gerektirir. Böylece, akışı yeni bir değer oluşturabilirsiniz. Yapılandırdığınız anahtarla StateFlow öğesini alabilirsiniz ve en son değeri toplayın.

Aşağıdaki snippet'te savedFilterType, bir StateFlow değişkenidir bir sohbet uygulamasında sohbet kanalları listesine uygulanan bir filtre türü depolar:

private const val CHANNEL_FILTER_SAVED_STATE_KEY = "ChannelFilterKey"

class ChannelViewModel(
    channelsRepository: ChannelsRepository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val savedFilterType: StateFlow<ChannelsFilterType> = savedStateHandle.getStateFlow(
        key = CHANNEL_FILTER_SAVED_STATE_KEY, initialValue = ChannelsFilterType.ALL_CHANNELS
    )

    private val filteredChannels: Flow<List<Channel>> =
        combine(channelsRepository.getAll(), savedFilterType) { channels, type ->
            filter(channels, type)
        }.onStart { emit(emptyList()) }

    fun setFiltering(requestType: ChannelsFilterType) {
        savedStateHandle[CHANNEL_FILTER_SAVED_STATE_KEY] = requestType
    }

    /*...*/
}

enum class ChannelsFilterType {
    ALL_CHANNELS, RECENT_CHANNELS, ARCHIVED_CHANNELS
}

Kullanıcı her yeni filtre türü seçtiğinde setFiltering çağrılır. Bu anahtarla saklanan SavedStateHandle işlevinde yeni bir değer kaydeder _CHANNEL_FILTER_SAVED_STATE_KEY_. savedFilterType, anahtara depolanan en son değer. filteredChannels şu akışa abone: veya kanal filtreleme yöntemini kullanmak.

Şu konular hakkında daha fazla bilgi için SavedStateHandle dokümanlarına göz atın: getStateFlow() API.

Özet

Aşağıdaki tabloda, bu bölümde ele alınan API'ler ve ne zaman kullanılmaları gerektiği özetlenmiştir. kullanıcı arayüzü durumunu kaydetmek için:

Etkinlik Kullanıcı arayüzü mantığı ViewModel içinde iş mantığı
Yapılandırma değişiklikleri rememberSaveable Otomatik
Sistem tarafından başlatılan işlem ölümü rememberSaveable SavedStateHandle

Kullanılacak API, eyaletin nerede bulunduğuna ve bu eyaletin gerekiyor. Kullanıcı arayüzü mantığında kullanılan durum için rememberSaveable değerini kullanın. Örneğin, iş mantığı için kullanılan bir ifadedir (ViewModel içinde tutarsanız, SavedStateHandle kullanarak kaydedebilirsiniz.

Paket API'lerini (rememberSaveable ve SavedStateHandle) şu amaçlarla kullanmalısınız: kullanıcı arayüzü durumunu depolama. Bu veriler, geri yüklenmesi için gereken minimum veri miktarıdır diğer depolama mekanizmalarıyla birlikte kullanıcı arayüzünü önceki durumuna geri döndürür. Örneğin, Örneğin, kullanıcının baktığı bir profilin kimliğini pakette saklarsanız profil ayrıntıları gibi ağır verileri veri katmanından getirebilirsiniz.

Kullanıcı arayüzü durumunu kaydetmenin farklı yolları hakkında daha fazla bilgi için genel Kullanıcı Arayüzü Durumu belgelerini ve veri katmanı sayfasını inceleyebilirsiniz.

ziyaret edin.