Kullanıcı arayüzü durumu eklediğiniz Compose uygulamasında, kullanıcı arayüzünün Mantık veya iş mantığı için bunu gerektirir. Bu belgede şu iki ana konu ele alınmıştır: senaryoları ele alacağız.
En iyi uygulama
Kullanıcı arayüzü durumunu tüm kaynaklar arasındaki en düşük ortak üst öğeye composable'dan oluşuyor. Bulunduğunuz yere en yakın eyaleti korumanız gerekir emin olmanız gerekir. Devlet sahibinden, tüketicilere değiştirilemez durum ve etkinlikler gösterilir tıklayın.
En düşük ortak üst de Beste'nin dışında olabilir. Örneğin,
durum ViewModel
kaldırıldığında, iş mantığı önemlidir.
Bu sayfada, bu en iyi uygulama ayrıntılı olarak açıklanmakta ve dikkat edilmesi gereken bir uyarı bulunmaktadır.
Kullanıcı arayüzü durumu ve kullanıcı arayüzü mantığı türleri
Aşağıda, kullanılan kullanıcı arayüzü durumu ve mantık türlerinin tanımları verilmiştir bu belgenin tamamından bahsedeceğim.
Kullanıcı arayüzü durumu
Kullanıcı arayüzü durumu, kullanıcı arayüzünü açıklayan özelliktir. İki tür kullanıcı arayüzü vardır eyalet:
- Ekran kullanıcı arayüzü durumu, ekranda görüntülemeniz gereken ifadedir. Örneğin,
NewsUiState
sınıfı, gerekli haber makalelerini ve diğer bilgileri içerebilir oluşturmak istiyorum. Bu durum genellikle öğenin diğer katmanlarıyla uygulama verileri içerdiğinden hiyerarşik olarak yapılandırılmıştır. - Kullanıcı arayüzü öğesi durumu, öğelerin dışında kalan kullanıcı arayüzü öğelerinin
nasıl oluşturulduğunu etkiler. Kullanıcı arayüzü öğeleri gösterilebilir veya gizlenebilir.
yazı tipi, yazı tipi boyutu veya yazı tipi rengine sahip olduğundan emin olun. Android Görünümlerinde, Görünüm
doğası gereği durum bilgili olduğu için bu durumu yönetir. Son olarak da
veya sorgulayabilir.
get
ve metni içinTextView
sınıfınınset
yöntemlerini. Jetpack'te Oluşturma, durum composable'ın dışındadır ve hatta kaldırılabilir composable'ın yakın çevresinden çağrıda bulunan composable'a bir işlev veya durum tutucuyu ifade eder. Şu konum içinScaffoldState
buna bir örnektir:Scaffold
composable.
Mantık
Bir uygulamadaki mantık, iş mantığı veya kullanıcı arayüzü mantığı olabilir:
- İş mantığı, uygulama için ürün şartlarının uygulanmasıdır. dışı verilerdir. Örneğin, kullanıcı haber okuyucu uygulamasındaki bir makaleye yer işareti koyduğunda düğmeye dokunur. Yer işaretini bir dosyaya veya veritabanına kaydetmek için bu mantık genellikle alan adına veya veri katmanlarına yerleştirilir. Eyalet sahibi genellikle gösterdikleri yöntemleri çağırarak bu mantığı bu katmanlara delege eder.
- Kullanıcı arayüzü mantığı, ekranda kullanıcı arayüzü durumunun nasıl gösterileceğiyle ilgilidir. Örneğin, Örneğin, kullanıcı bir seçim yaptığında doğru arama çubuğu ipucunu liste içinde belirli bir öğeye gitmek için kaydırma mantığı veya gezinme mantığı Kullanıcı bir düğmeyi tıkladığında belirli bir ekrana yönlendirilir.
Kullanıcı arayüzü mantığı
Kullanıcı arayüzü mantığının durum okuması veya yazması gerektiğinde, durumu kullanıcı arayüzüne takip ederek kapsam belirlemelisiniz. Bunu başarmak için durumu, composable bir işlevde doğru düzeyde kaldırmanız gerekir. Alternatif olarak bunu, kullanıcı arayüzü yaşam döngüsü kapsamındaki bir düz durum tutucu sınıfında da yapın.
Aşağıda hem çözümler hem de ne zaman kullanılacağına dair açıklama yer almaktadır.
Eyalet sahibi olarak bestelenebilirler
composable'larda kullanıcı arayüzü mantığının ve kullanıcı arayüzü öğesi durumunun olması, çok basittir. Durumunuzu dahili olarak bir composable veya kaldırın.
Eyalet kaldırma gerekmez
Kaldırma durumu her zaman gerekli değildir. Durum, bir composable içinde dahili tutulabilir bu özelliği kullanabilirsiniz. Bu snippet'te, dokunarak genişletilen veya daraltılan bir composable var:
@Composable fun ChatBubble( message: Message ) { var showDetails by rememberSaveable { mutableStateOf(false) } // Define the UI element expanded state ClickableText( text = AnnotatedString(message.content), onClick = { showDetails = !showDetails } // Apply simple UI logic ) if (showDetails) { Text(message.timestamp) } }
showDetails
değişkeni, bu kullanıcı arayüzü öğesinin dahili durumudur. Yalnızca
ve ona uygulanan mantık çok basit.
Bu durumda devlete hizmet etmek, pek bir fayda sağlamaz. Dolayısıyla
dahili olarak bırakabiliriz. Bu sayede, bu composable, sahibi ve tek başına
genişletilmiş durumun veri kaynağıdır.
composable'ların içine kaldırma
Kullanıcı arayüzü öğenizin durumunu diğer composable'larla paylaşmanız ve kullanıcı arayüzü uygulamanız gerekiyorsa bunu kullanıcı arayüzü hiyerarşisinde daha yukarılara çıkarabilirsiniz. Bu sayede composable'larınızı daha fazla yeniden kullanabilir ve daha kolay test edebilirsiniz.
Aşağıdaki örnek, iki farklı işlev sunan bir sohbet uygulamasıdır:
JumpToBottom
düğmesi, ileti listesini en alta kaydırır. Düğme liste durumunda kullanıcı arayüzü mantığı gerçekleştirir.- Kullanıcı yeni bir ileti gönderdikten sonra
MessagesList
listesi en alta gider mesaj. UserInput, liste durumunda kullanıcı arayüzü mantığı gerçekleştirir.
![JumpToBottom düğmesi olan sohbet uygulaması ve yeni mesajlarda ekranı en alta kaydır](https://developer.android.google.cn/static/develop/ui/compose/images/state-hoisting-chat.png?authuser=5&hl=tr)
JumpToBottom
düğmesi bulunan Chat uygulamasında yeni mesajlarda ekranı aşağı kaydırınOluşturulabilir hiyerarşi aşağıdaki gibidir:
![Sohbet composable ağaç](https://developer.android.google.cn/static/develop/ui/compose/images/state-hoisting-initial-tree.png?authuser=5&hl=tr)
Uygulamanın şunları yapabilmesi için LazyColumn
durumu görüşme ekranına taşınır.
kullanıcı arayüzü mantığını uygulayın ve bunu gerektiren tüm composable'lardan durumu okuyun:
![LazyColumn durumunu LazyColumn'tan ConversationScreen'e kaldırma](https://developer.android.google.cn/static/develop/ui/compose/images/state-hoisting-animated.gif?authuser=5&hl=tr)
LazyColumn
durumu LazyColumn
noktasından ConversationScreen
noktasına kaldırılıyorSon olarak composable'lar şöyle:
![ConversationScreen'a getirilen LazyListState ve sohbet composable ağacı](https://developer.android.google.cn/static/develop/ui/compose/images/state-hoisting-passing-state.png?authuser=5&hl=tr)
LazyListState
ile sohbet composable ağaç ConversationScreen
konumuna kaldırıldıKod şu şekildedir:
@Composable private fun ConversationScreen(/*...*/) { val scope = rememberCoroutineScope() val lazyListState = rememberLazyListState() // State hoisted to the ConversationScreen MessagesList(messages, lazyListState) // Reuse same state in MessageList UserInput( onMessageSent = { // Apply UI logic to lazyListState scope.launch { lazyListState.scrollToItem(0) } }, ) } @Composable private fun MessagesList( messages: List<Message>, lazyListState: LazyListState = rememberLazyListState() // LazyListState has a default value ) { LazyColumn( state = lazyListState // Pass hoisted state to LazyColumn ) { items(messages, key = { message -> message.id }) { item -> Message(/*...*/) } } val scope = rememberCoroutineScope() JumpToBottom(onClicked = { scope.launch { lazyListState.scrollToItem(0) // UI logic being applied to lazyListState } }) }
LazyListState
, olması gereken kullanıcı arayüzü mantığı için gereken kadar yükseltilir
geçerlidir. composable işlevde başlatıldığı için,
Bestenin yaşam döngüsü.
lazyListState
öğesinin, MessagesList
yönteminde
varsayılan değere (rememberLazyListState()
) sahip. Bu, Compose'da sık kullanılan bir kalıptır.
composable'ları yeniden kullanılabilir ve esnek hale getirir. Ardından composable'ı kullanarak
uygulamanın farklı bölümlerinde durumu kontrol
etmelerine gerek yoktur. Bu
durum genellikle bir composable'ı test ederken veya önizlerken geçerlidir. İşte bu şekilde
Durumunu LazyColumn
tanımlar.
![LazyListState için en düşük ortak üst öğe ConversationScreen'dir](https://developer.android.google.cn/static/develop/ui/compose/images/state-hoisting-lca.png?authuser=5&hl=tr)
LazyListState
için en düşük ortak üst öğe: ConversationScreen
Eyalet sahibi olarak düz eyalet sahibi sınıfı
Bir composable, bir veya daha fazla durum içeren karmaşık kullanıcı arayüzü mantığı içerdiğinde bir kullanıcı arayüzü öğesinin alanına eklenirse bu sorumluluğu sahipler gibi. Bu, composable'ın mantığını ve karmaşıklığını azaltır. Bu yaklaşım, endişelerin ayrılması ilkesi: composable devreye girer ya da kullanıcı arayüzü öğeleri yayınlamanın bir listesini içerir ve durum tutucu, kullanıcı arayüzü mantığını ve kullanıcı arayüzünü içerir öğe durumunu kontrol edin.
Düz durum tutucu sınıfları, sayfanızı arayan kişilere composable fonksiyonunu kullanarak bu mantığı yazma zorunluluğu yoktur.
Bu sade sınıflar Beste'de oluşturulur ve hatırlanır. Çünkü
composable'ın yaşam döngüsünü takip ederseniz
rememberNavController()
veya rememberLazyListState()
gibi kitaplık oluşturun.
Bunun bir örneği LazyListState
düz durum tutucudur.
sınıfı, LazyColumn
kullanıcı arayüzü karmaşıklığını kontrol etmek için Compose'da uygulandı
veya LazyRow
.
// LazyListState.kt @Stable class LazyListState constructor( firstVisibleItemIndex: Int = 0, firstVisibleItemScrollOffset: Int = 0 ) : ScrollableState { /** * The holder class for the current scroll position. */ private val scrollPosition = LazyListScrollPosition( firstVisibleItemIndex, firstVisibleItemScrollOffset ) suspend fun scrollToItem(/*...*/) { /*...*/ } override suspend fun scroll() { /*...*/ } suspend fun animateScrollToItem() { /*...*/ } }
LazyListState
,LazyColumn
Bu kullanıcı arayüzü öğesi için scrollPosition
. Ayrıca,
belirli bir öğeye gidin.
Gördüğünüz gibi bir composable'ın sorumluluklarının artması, bir gerekliliktir. Sorumluluklar kullanıcı arayüzü mantığı veya yalnızca durum miktarına bakılır.
Yaygın olarak kullanılan bir diğer model, uygulamadaki kök composable işlevlerin karmaşıklığı. Bu tür bir sınıfı şunlar için kullanabilirsiniz: gezinme durumu ve ekran boyutlandırma gibi uygulama düzeyindeki durumu kapsamalıdır. Tam bunun açıklamasını kullanıcı arayüzü mantığı ve durum tutucu sayfasında bulabilirsiniz.
İş mantığı
Kullanıcı arayüzü mantığından ve Kullanıcı arayüzü öğesi durumunda, ekran düzeyinde durum tutucu aşağıdakilerden sorumlu olur: görevler:
- Aynı işleve sahip uygulamanın iş mantığına erişmesini sağlama genellikle hiyerarşinin diğer katmanlarına (ör. işletme, veri katmanından yararlanın.
- Uygulama verileri belirli bir ekranda sunum için hazırlanıyor, Bu da ekranın kullanıcı arayüzü durumu olur.
Eyalet sahibi olarak ViewModels'ler
Android geliştirmede AAC ViewModel'lerin avantajları, onları iş mantığına erişim sağlamak ve uygulama verilerini hazırlamak için ekranda gösterilmesi için kullanılır.
Kullanıcı arayüzü durumunu ViewModel
içine kaldırdığınızda, öğeyi
Beste.
![ViewModel'e kaldırılan durum, Beste'nin dışında depolanır.](https://developer.android.google.cn/static/develop/ui/compose/images/state-hoisting-vm.png?authuser=5&hl=tr)
ViewModel
değerine kaldırılan durum, Beste'nin dışında depolanır.ViewModel'ler Beste'nin bir parçası olarak depolanmaz. Sağlayan:
ve bir ViewModelStoreOwner
kapsamında değerlendirilirler. Bu,
Bir gezinme grafiğinin etkinliği, bölümü, gezinme grafiği veya hedefi. Örneğin,
ViewModel
kapsam hakkında daha fazla bilgi için dokümanları inceleyebilirsiniz.
Bu durumda ViewModel
, şuna ait bilginin kaynağı ve en alçak ortak atadır:
Kullanıcı arayüzü durumu.
Ekran kullanıcı arayüzü durumu
Yukarıdaki tanımlara göre, ekran kullanıcı arayüzü durumu, işletme
kurallar. Ekran düzeyi durumu sahibi, bu işlemden sorumlu
ekran kullanıcı arayüzü durumunun genellikle ekran düzeyi durumunda kaldırıldığı anlamına gelir
öğesi, bu örnekte bir ViewModel
.
Bir sohbet uygulamasının ConversationViewModel
özelliğini ve ekranın nasıl göründüğünü düşünün
Değiştirilecek kullanıcı arayüzü durumu ve etkinlikler:
class ConversationViewModel( channelId: String, messagesRepository: MessagesRepository ) : ViewModel() { val messages = messagesRepository .getLatestMessages(channelId) .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000), initialValue = emptyList() ) // Business logic fun sendMessage(message: Message) { /* ... */ } }
Özelleştirilebilir öğeler, ViewModel
içine kaldırılan ekran kullanıcı arayüzü durumunu kullanır. Şunları yapmalısınız:
enjekte etmek için ViewModel
örneğini ekran düzeyinde composable'larınıza ekleyin
iş mantığına erişmelerini sağlar.
Aşağıda, ekran düzeyinde bir composable'da kullanılan ViewModel
örneği verilmiştir.
Burada, composable ConversationScreen()
, kaldırılan ekran kullanıcı arayüzü durumunu tüketir
ViewModel
:
@Composable private fun ConversationScreen( conversationViewModel: ConversationViewModel = viewModel() ) { val messages by conversationViewModel.messages.collectAsStateWithLifecycle() ConversationScreen( messages = messages, onSendMessage = { message: Message -> conversationViewModel.sendMessage(message) } ) } @Composable private fun ConversationScreen( messages: List<Message>, onSendMessage: (Message) -> Unit ) { MessagesList(messages, onSendMessage) /* ... */ }
Gayrimenkul sondajı
"Mülkü ayrıntılı inceleme", verilerin iç içe yerleştirilmiş birkaç alt öğeden geçirilmesini ifade eder içerikleri okundukları konuma taşımalıdır.
Compose'da sondajın gösterilebileceği tipik bir örnek, ekran düzeyi durum tutucusunu üst düzeye yerleştirin ve aşağı durumu iletin ve . Bu da aşırı yüklenmeye yol açabilir. composable işlevler imzaları gibidir.
Etkinlikleri ayrı lambda parametreleri olarak göstermek, composable fonksiyonunun görünürlüğünü en üst düzeye çıkararak hakkında daha fazla bilgi edindiniz. Ne işe yaradığını bir bakışta görebilirsiniz.
Mülk işleme, kapsüllemek için sarmalayıcı sınıfları oluşturmak yerine tercih edilir durumu ve olayları tek bir yerde toplaması sayesinde, sorumluluklar var. Sarmalayıcı sınıfların olmaması, composable'lara yalnızca ihtiyaç duydukları parametreleri iletme ihtimali vardır. Bu da alıştırma da yapın.
Bu etkinlikler gezinme etkinlikleriyse de aynı en iyi uygulama geçerlidir. gezinme dokümanlarından bu konu hakkında daha fazla bilgi edinebilirsiniz.
Bir performans sorunu tespit ettiyseniz okumayı ertelemeyi de seçebilirsiniz durumu. Daha fazla bilgi edinmek için performans belgelerini inceleyebilirsiniz.
kullanıcı arayüzü öğesinin durumu
Kullanıcı arayüzü öğesi durumunu, okuması veya yazması gereken bir iş mantığıdır.
Sohbet uygulaması örneğine devam edersek uygulama, kullanıcı önerilerini
Kullanıcı @
ve bir ipucu yazdığında grup sohbeti. Bu öneriler
kullanıcı önerileri listesini hesaplama mantığı ve veri katmanı
iş mantığına dayanır. Bu özellik aşağıdaki gibi görünür:
![Kullanıcı "@" ve ipucu yazdığında grup sohbetinde kullanıcı önerilerini gösteren özellik](https://developer.android.google.cn/static/develop/ui/compose/images/state-hoisting-suggestions.png?authuser=5&hl=tr)
@
ve bir ipucu yazdığında grup sohbetinde kullanıcı önerilerini gösteren özellikBu özelliği uygulamak için kullanılan ViewModel
aşağıdaki gibi görünür:
class ConversationViewModel(/*...*/) : ViewModel() { // Hoisted state var inputMessage by mutableStateOf("") private set val suggestions: StateFlow<List<Suggestion>> = snapshotFlow { inputMessage } .filter { hasSocialHandleHint(it) } .mapLatest { getHandle(it) } .mapLatest { repository.getSuggestions(it) } .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000), initialValue = emptyList() ) fun updateInput(newInput: String) { inputMessage = newInput } }
inputMessage
, TextField
durumunu depolayan bir değişkendir. Her
Kullanıcı yeni bir giriş yazarsa uygulama, suggestions
üretmek için iş mantığını çağırır.
suggestions
, ekran kullanıcı arayüzü durumudur ve veri toplama işlevi kullanılarak Compose kullanıcı arayüzünden tüketilir
StateFlow
.
Uyarı
Bazı Compose kullanıcı arayüzü öğesi durumlarında ViewModel
öğesine kaldırma işlemi gerekebilir
dikkat edilmesi gereken birkaç nokta var. Örneğin, Compose kullanıcı arayüzü öğelerinin bazı durum sahipleri
ve durumu değiştirme yöntemleri
sunulabilir. Bunlardan bazıları,
animasyonları tetikleyebilir. Bu askıya alma işlevleri
bunlarıCoroutineScope
Beste.
Uygulama çekmecesinin içeriğinin dinamik olduğunu ve alıp yenilemeniz gerektiğini varsayalım.
veri katmanından kaldırmanız gerekir. Çekmece durumunu, dikey biçimde
Bu öğede hem kullanıcı arayüzünü hem de iş mantığını çağırabilmeniz için ViewModel
bunu yapabilirsiniz.
Ancak, DrawerState
close()
Oluştur kullanıcı arayüzündeki viewModelScope
, şu tür bir çalışma zamanı istisnasına neden oluyor:
IllegalStateException
yazan bir mesajda "a"
MonotonicFrameClock
bu konumda kullanılamıyor
CoroutineContext”
.
Bunu düzeltmek için Beste'ye ayarlanmış bir CoroutineScope
kullanın. Sağladığı
CoroutineContext
içindeki MonotonicFrameClock
askıya alma işlevleri kullanılabilir.
Bu kilitlenmeyi düzeltmek için eş yordanın CoroutineContext
ayarını değiştirin
Beste'ye ayarlanan bir genel bakış için ViewModel
. Bu kod aşağıdaki gibi görünebilir:
class ConversationViewModel(/*...*/) : ViewModel() { val drawerState = DrawerState(initialValue = DrawerValue.Closed) private val _drawerContent = MutableStateFlow(DrawerContent.Empty) val drawerContent: StateFlow<DrawerContent> = _drawerContent.asStateFlow() fun closeDrawer(uiScope: CoroutineScope) { viewModelScope.launch { withContext(uiScope.coroutineContext) { // Use instead of the default context drawerState.close() } // Fetch drawer content and update state _drawerContent.update { content } } } } // in Compose @Composable private fun ConversationScreen( conversationViewModel: ConversationViewModel = viewModel() ) { val scope = rememberCoroutineScope() ConversationScreen(onCloseDrawer = { conversationViewModel.closeDrawer(uiScope = scope) }) }
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
ziyaret edin.Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir
- Oluşturma'da kullanıcı arayüzü durumunu kaydet
- Listeler ve ızgaralar
- Compose kullanıcı arayüzünüzü tasarlama