Eyaletinizin çekildiği yere ve gerekli mantığa bağlı olarak, kullanıcı arayüzü durumunuzu depolamak ve geri yüklemek için farklı API'ler kullanabilirsiniz. Her uygulama bunu en iyi şekilde gerçekleştirmek için bir API kombinasyonu kullanır.
Herhangi bir Android uygulaması, etkinlik veya işlem yeniden oluşturma nedeniyle kullanıcı arayüzü durumunu kaybedebilir. Bu durum kaybı aşağıdaki olaylardan kaynaklanabilir:
- Yapılandırma değişiklikleri. Yapılandırma değişikliği manuel olarak işlenmediği sürece etkinlik kaldırılır ve yeniden oluşturulur.
- Sistem tarafından başlatılan işlem ölümü. Uygulama arka planda çalışır ve cihaz, diğer işlemler tarafından kullanılmak üzere kaynakları (ör. bellek) boşaltır.
Bu etkinliklerden sonraki durumun korunması, olumlu bir kullanıcı deneyimi için esastır. Kalıcı olacak durumu seçmek, uygulamanızın benzersiz kullanıcı akışlarına bağlıdır. En iyi uygulama olarak, en azından kullanıcı girişini ve gezinmeyle ilgili durumu korumalısınız. Örneğin, bir listenin kaydırma konumu, kullanıcının daha fazla bilgi edinmek istediği öğenin kimliği, kullanıcı tercihlerinin seçimi veya metin alanlarına giriş işlemleri bu kapsama girer.
Bu sayfada, eyaletinizin nereye çekildiğine ve buna ihtiyaç duyulan mantığa bağlı olarak kullanıcı arayüzü durumunu depolamak için kullanılabilecek API'ler özetlenmektedir.
Kullanıcı arayüzü mantığı
Eyaletiniz kullanıcı arayüzünde composable Functions'ta veya Beste kapsamındaki sade durum sahibi sınıflarında bulunuyorsa etkinlik ve süreç yeniden oluşturma genelinde durumu korumak için rememberSaveable
aracını kullanabilirsiniz.
Aşağıdaki snippet'te rememberSaveable
, tek bir boole kullanıcı arayüzü öğesi durumunu depolamak için kullanılmıştır:
@Composable fun ChatBubble( message: Message ) { var showDetails by rememberSaveable { mutableStateOf(false) } ClickableText( text = AnnotatedString(message.content), onClick = { showDetails = !showDetails } ) if (showDetails) { Text(message.timestamp) } }
showDetails
, sohbet balonunun daraltılmış veya genişletilmiş halini saklayan bir boole değişkenidir.
rememberSaveable
, kullanıcı arayüzü öğesinin durumunu kayıtlı örnek durum mekanizması aracılığıyla bir Bundle
içinde depolar.
Temel türleri pakete otomatik olarak depolayabilir. Durumunuz, veri sınıfı gibi temel olmayan bir türde bulunuyorsa Parcelize
ek açıklamasını kullanma, listSaver
ve mapSaver
gibi Oluşturma API'lerini kullanma veya Compose çalışma zamanı Saver
sınıfını genişleten özel tasarruf sınıfı uygulama gibi farklı depolama mekanizmaları kullanabilirsiniz. Bu yöntemler hakkında daha fazla bilgi edinmek için Durumu depolama yöntemleri belgelerine bakın.
Aşağıdaki snippet'te rememberSaveable
kullanılan LazyColumn
veya LazyRow
kaydırma durumundan oluşan rememberLazyListState
Compose API'leri LazyListState
depolar. Kaydırma durumunu saklayıp geri yükleyebilen özel bir koruyucu olan LazyListState.Saver
kullanır. Bir etkinlik veya işlem yeniden oluşturulduktan sonra (örneğin, cihaz yönünü değiştirme gibi bir yapılandırma değişikliğinden sonra) kaydırma durumu korunur.
@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 bilgi, etkinliğinizdeki onSaveInstanceState()
çağrıları gibi kendisine veri yazan diğer API'ler tarafından da paylaşılır. Bununla birlikte, bu Bundle
öğesinin boyutu sınırlıdır ve büyük nesnelerin depolanması, çalışma zamanında TransactionTooLarge
istisnalarına yol açabilir. Bu, özellikle aynı Bundle
öğesinin uygulama genelinde kullanıldığı tekil Activity
uygulamalarında sorunlu olabilir.
Bu tür kilitlenmeleri önlemek için karmaşık nesneleri veya nesne listelerini pakette depolamamalısınız.
Bunun yerine, kimlikler veya anahtarlar gibi gereken minimum durumu depolayın ve bunları, daha karmaşık kullanıcı arayüzü durumlarını kalıcı depolama gibi diğer mekanizmalara geri yükleme yetkisi vermek için kullanın.
Bu tasarım seçenekleri, uygulamanızın belirli kullanım alanlarına ve kullanıcıların uygulamanızın nasıl davranmasını beklediğine bağlıdır.
Eyalet geri yüklemesini doğrulama
Etkinlik veya işlem yeniden oluşturulduğunda, E-posta Yaz öğelerinizde rememberSaveable
ile depolanan durumun doğru şekilde geri yüklendiğini doğrulayabilirsiniz. Bunu başarmak için, StateRestorationTester
gibi belirli API'ler vardır. Daha fazla bilgi edinmek için Test belgelerine bakın.
İş mantığı
Kullanıcı arayüzü öğenizin durumu, iş mantığının gerektirdiği için ViewModel
değerine ayarlanmışsa ViewModel
API'lerini kullanabilirsiniz.
Android uygulamanızda ViewModel
kullanmanın temel avantajlarından biri, yapılandırma değişikliklerini ücretsiz olarak işlemesidir. Bir yapılandırma değişikliği olduğunda etkinlik kaldırılıp yeniden oluşturulduğunda ViewModel
öğesine taşınan kullanıcı arayüzü durumu bellekte tutulur. Yeniden oluşturma işleminden sonra eski ViewModel
örneği, yeni etkinlik örneğine eklenir.
Ancak ViewModel
örneği, sistem tarafından başlatılan işlem ölümünden sonra kurtarılamaz.
Kullanıcı arayüzü durumunun bu durumu aşmasını sağlamak için SavedStateHandle
API'yi içeren ViewModel için Kayıtlı Durum modülünü kullanın.
En iyi uygulama
SavedStateHandle
, kullanıcı arayüzü durumunu depolamak için de Bundle
mekanizmasını kullanır. Bu nedenle, bunu yalnızca basit kullanıcı arayüzü öğesi durumunu depolamak için kullanmalısınız.
İş kuralları uygulanarak ve uygulamanızın kullanıcı arayüzü dışındaki katmanlarına erişilerek oluşturulan ekran kullanıcı arayüzü durumu, olası karmaşıklığı ve boyutundan dolayı SavedStateHandle
içinde depolanmamalıdır. Karmaşık veya büyük verileri depolamak için yerel kalıcı depolama gibi farklı mekanizmalar kullanabilirsiniz. İşlemin yeniden oluşturulmasından sonra ekran, SavedStateHandle
içinde depolanan geri yüklenmiş geçici durumla (varsa) yeniden oluşturulur ve ekran kullanıcı arayüzü durumu da veri katmanından tekrar üretilir.
SavedStateHandle
API
SavedStateHandle
, kullanıcı arayüzü öğesi durumunu depolamak için farklı API'lere sahiptir. En önemlisi şudur:
Oluştur State |
saveable() |
---|---|
StateFlow |
getStateFlow() |
State
oluştur
Kullanıcı arayüzü öğesi durumunu MutableState
olarak okuyup yazmak için SavedStateHandle
saveable
API'sini kullanın. Böylece minimum kod kurulumuyla etkinlikten ve süreç yeniden oluşturmada hayatta kalır.
saveable
API, kullanıma hazır temel türleri destekler ve rememberSaveable()
gibi özel koruyucuları kullanmak için bir stateSaver
parametresi alır.
Aşağıdaki snippet'te message
, kullanıcı girişi türlerini bir TextField
öğesine depolar:
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) } ) }
saveable
API'yi kullanma hakkında daha fazla bilgi için SavedStateHandle
belgelerine bakın.
StateFlow
Kullanıcı arayüzü öğesi durumunu depolamak ve SavedStateHandle
'dan akış olarak tüketmek için getStateFlow()
kullanın. StateFlow
salt okunurdur ve API, akışı yeni bir değer yayınlayacak şekilde değiştirebilmeniz için bir anahtar belirtmenizi gerektirir. Yapılandırdığınız anahtarla StateFlow
öğesini alabilir ve en son değeri toplayabilirsiniz.
Aşağıdaki snippet'te savedFilterType
, bir sohbet uygulamasındaki sohbet kanalları listesine uygulanan bir filtre türünü depolayan StateFlow
değişkenidir:
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ının yeni bir filtre türü seçtiğinde setFiltering
çağrılır. Bu işlem, _CHANNEL_FILTER_SAVED_STATE_KEY_
anahtarıyla depolanan SavedStateHandle
alanına yeni bir değer kaydeder. savedFilterType
, anahtarda depolanan en son değeri yayınlayan bir akıştır. filteredChannels
, kanal filtrelemesi gerçekleştirmek için akışa abone olur.
getStateFlow()
API hakkında daha fazla bilgi için SavedStateHandle
belgelerine bakın.
Özet
Aşağıdaki tabloda, bu bölümde ele alınan API'ler ve kullanıcı arayüzü durumunu kaydetmek için her birinin ne zaman kullanılacağı özetlenmiştir:
Etkinlik | Kullanıcı arayüzü mantığı | ViewModel konumunda 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, durumun nerede tutulduğuna ve gerektirdiği mantığa bağlıdır. Kullanıcı arayüzü mantığında kullanılan durum için rememberSaveable
kullanın. İş mantığında kullanılan eyalet için ViewModel
içinde tutuyorsanız SavedStateHandle
kullanarak kaydedin.
Az miktarda kullanıcı arayüzü durumu depolamak için paket API'lerini (rememberSaveable
ve SavedStateHandle
) kullanmanız gerekir. Bu veri, kullanıcı arayüzünü diğer depolama mekanizmalarıyla birlikte önceki durumuna geri yüklemek için gereken minimum değerdir. Örneğin, kullanıcının pakette baktığı bir profilin kimliğini depolarsanı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ü Durumunu Kaydetme belgelerine ve mimari kılavuzunun veri katmanı sayfasına bakın.
Sizin için önerilenler
- Not: Bağlantı metni JavaScript kapalıyken görüntülenir
- Eyalet nereden kaldırılır?
- State ve Jetpack Compose
- Listeler ve ızgaralar