Kullanıcı arayüzü katmanı kılavuzunda, kullanıcı arayüzü katmanı için kullanıcı arayüzü durumunu oluşturma ve yönetme yöntemi olarak tek yönlü veri akışı (UDF) ele alınmaktadır.
Ayrıca, UDF yönetimini durum tutucu adı verilen özel bir sınıfa devretmenin avantajlarını da vurgular. Durum bilgisi depolayıcıyı ViewModel veya düz bir sınıf aracılığıyla uygulayabilirsiniz. Bu belgede, paydaşlar ve kullanıcı arayüzü katmanındaki rolleri daha ayrıntılı bir şekilde ele alınmaktadır.
Bu belgenin sonunda, kullanıcı arayüzü katmanındaki uygulama durumunu (yani kullanıcı arayüzü durumu üretim ardışık düzenini) nasıl yöneteceğinizi anlamış olacaksınız. Aşağıdakileri anlayabilmeli ve bilmelisiniz:
- Kullanıcı arayüzü katmanında bulunan kullanıcı arayüzü durumu türlerini anlama.
- Kullanıcı arayüzü katmanında bu kullanıcı arayüzü durumlarında çalışan mantık türlerini anlayın.
- Bir durum bilgisi depolayıcının (ör.
ViewModelveya sınıf) uygun uygulamasını nasıl seçeceğinizi bilin.
Kullanıcı arayüzü durum üretimi ardışık düzeninin öğeleri
Kullanıcı arayüzü durumu ve bunu üreten mantık, kullanıcı arayüzü katmanını tanımlar.
Kullanıcı arayüzü durumu
UI state (Kullanıcı arayüzü durumu), kullanıcı arayüzünü açıklayan özelliktir. İki tür kullanıcı arayüzü durumu vardır:
- Ekran kullanıcı arayüzü durumu, ekranda göstermeniz gereken şeydir. Örneğin, bir
NewsUiStatesınıfı, kullanıcı arayüzünü oluşturmak için gereken haber makalelerini ve diğer bilgileri içerebilir. Bu durum genellikle uygulama verilerini içerdiğinden hiyerarşinin diğer katmanlarıyla bağlantılıdır. - Kullanıcı arayüzü öğesi durumu, kullanıcı arayüzü öğelerine özgü olup nasıl oluşturulduklarını etkileyen özellikleri ifade eder. Bir kullanıcı arayüzü öğesi gösterilebilir veya gizlenebilir ve belirli bir yazı tipi, yazı tipi boyutu ya da yazı tipi rengine sahip olabilir. Jetpack Compose'da durum, composable'ın dışındadır ve hatta composable'ın hemen yakınından composable işlevini çağıran veya bir durum bilgisi depolayıcıya taşıyabilirsiniz. Buna örnek olarak,
Scaffoldcomposable'ı içinScaffoldStateverilebilir.
Mantık
Uygulama verileri ve kullanıcı etkinlikleri, kullanıcı arayüzü durumunun zaman içinde değişmesine neden olduğundan kullanıcı arayüzü durumu statik bir özellik değildir. Mantık, kullanıcı arayüzü durumunun hangi bölümlerinin değiştiği, neden değiştiği ve ne zaman değişmesi gerektiği de dahil olmak üzere değişikliğin ayrıntılarını belirler.
Bir uygulamadaki mantık, iş mantığı veya kullanıcı arayüzü mantığı olabilir:
- İş mantığı, uygulama verileriyle ilgili ürün şartlarının uygulanmasıdır. Örneğin, kullanıcı düğmeye dokunduğunda bir haber okuyucu uygulamasında makaleye yer işareti ekleme. Bir yer işaretini dosyaya veya veritabanına kaydetme mantığı genellikle alan veya veri katmanlarına yerleştirilir. Durum bilgisi depolayıcı genellikle bu mantığı, sundukları yöntemleri çağırarak bu katmanlara devreder.
- Kullanıcı arayüzü mantığı, kullanıcı arayüzü durumunun ekranda nasıl görüntüleneceğiyle ilgilidir. Örneğin, kullanıcı bir kategori seçtiğinde doğru arama çubuğu ipucunu alma, listede belirli bir öğeye kaydırma veya kullanıcı bir düğmeyi tıkladığında belirli bir ekrana gitme mantığı.
Android yaşam döngüsü ve kullanıcı arayüzü durumu ile mantık türleri
Kullanıcı arayüzü katmanı iki bölümden oluşur: biri kullanıcı arayüzü yaşam döngüsüne bağlıdır, diğeri ise bağımsızdır. Bu ayrım, her bölümün kullanabileceği veri kaynaklarını belirler ve bu nedenle farklı türde kullanıcı arayüzü durumu ve mantığı gerektirir.
- Kullanıcı arayüzü yaşam döngüsünden bağımsız: Kullanıcı arayüzü katmanının bu kısmı, uygulamanın veri üreten katmanlarıyla (veri veya alan katmanları) ilgilenir ve iş mantığı tarafından tanımlanır. Yaşam döngüsü, yapılandırma değişiklikleri ve kullanıcı arayüzünde
Activityyeniden oluşturma, kullanıcı arayüzü durumu üretim ardışık düzeninin etkin olup olmadığını etkileyebilir ancak üretilen verilerin geçerliliğini etkilemez. - Kullanıcı arayüzü yaşam döngüsüne bağlı: Kullanıcı arayüzü katmanının bu bölümü, kullanıcı arayüzü mantığıyla ilgilenir ve yaşam döngüsü veya yapılandırma değişikliklerinden doğrudan etkilenir. Bu değişiklikler, içinde okunan veri kaynaklarının geçerliliğini doğrudan etkiler ve bu nedenle durumu yalnızca yaşam döngüsü etkin olduğunda değişebilir. Çalışma zamanı izinleri ve yerelleştirilmiş dizeler gibi yapılandırmaya bağlı kaynakları almak buna örnek verilebilir.
Yukarıdaki bilgiler aşağıdaki tabloda özetlenmiştir:
| Kullanıcı arayüzü yaşam döngüsünden bağımsız | Kullanıcı arayüzü yaşam döngüsüne bağlı |
|---|---|
| İş mantığı | Kullanıcı Arayüzü Mantığı |
| Ekran kullanıcı arayüzü durumu |
Kullanıcı arayüzü durumu üretim ardışık düzeni
Kullanıcı arayüzü durumu üretim hattı, kullanıcı arayüzü durumu üretmek için gerçekleştirilen adımları ifade eder. Bu adımlar, daha önce tanımlanan mantık türlerinin uygulanmasından oluşur ve tamamen kullanıcı arayüzünüzün ihtiyaçlarına bağlıdır. Bazı kullanıcı arayüzleri, ardışık düzenin hem kullanıcı arayüzü yaşam döngüsünden bağımsız hem de kullanıcı arayüzü yaşam döngüsüne bağımlı kısımlarından, birinden veya ikisinden de yararlanabilir.
Yani, kullanıcı arayüzü katmanı işlem hattının aşağıdaki permütasyonları geçerlidir:
Kullanıcı arayüzü durumu, kullanıcı arayüzü tarafından üretilir ve yönetilir. Örneğin, basit ve yeniden kullanılabilir bir temel sayaç:
@Composable fun Counter() { // The UI state is managed by the UI itself var count by remember { mutableStateOf(0) } Row { Button(onClick = { ++count }) { Text(text = "Increment") } Button(onClick = { --count }) { Text(text = "Decrement") } } }Kullanıcı arayüzü mantığı → Kullanıcı arayüzü. Örneğin, kullanıcının listenin en üstüne gitmesine olanak tanıyan bir düğmeyi gösterme veya gizleme.
@Composable fun ContactsList(contacts: List<Contact>) { val listState = rememberLazyListState() val isAtTopOfList by remember { derivedStateOf { listState.firstVisibleItemIndex < 3 } } // Create the LazyColumn with the lazyListState ... // Show or hide the button (UI logic) based on the list scroll position AnimatedVisibility(visible = !isAtTopOfList) { ScrollToTopButton() } }İş mantığı → kullanıcı arayüzü. Ekrandaki mevcut kullanıcının fotoğrafını gösteren bir kullanıcı arayüzü öğesi.
@Composable fun UserProfileScreen(viewModel: UserProfileViewModel = hiltViewModel()) { // Read screen UI state from the business logic state holder val uiState by viewModel.uiState.collectAsStateWithLifecycle() // Call on the UserAvatar Composable to display the photo UserAvatar(picture = uiState.profilePicture) }İş mantığı → kullanıcı arayüzü mantığı → kullanıcı arayüzü. Belirli bir kullanıcı arayüzü durumu için ekranda doğru bilgileri görüntülemek üzere kaydırılan kullanıcı arayüzü öğesi.
@Composable fun ContactsList(viewModel: ContactsViewModel = hiltViewModel()) { // Read screen UI state from the business logic state holder val uiState by viewModel.uiState.collectAsStateWithLifecycle() val contacts = uiState.contacts val deepLinkedContact = uiState.deepLinkedContact val listState = rememberLazyListState() // Create the LazyColumn with the lazyListState ... // Perform UI logic that depends on information from business logic if (deepLinkedContact != null && contacts.isNotEmpty()) { LaunchedEffect(listState, deepLinkedContact, contacts) { val deepLinkedContactIndex = contacts.indexOf(deepLinkedContact) if (deepLinkedContactIndex >= 0) { // Scroll to deep linked item listState.animateScrollToItem(deepLinkedContactIndex) } } } }
Kullanıcı arayüzü durumu oluşturma ardışık düzenine her iki mantık türünün de uygulandığı durumlarda iş mantığı her zaman kullanıcı arayüzü mantığından önce uygulanmalıdır. Kullanıcı arayüzü mantığından sonra iş mantığını uygulamaya çalışmak, iş mantığının kullanıcı arayüzü mantığına bağlı olduğu anlamına gelir. Aşağıdaki bölümlerde, farklı mantık türleri ve durum bilgisi depolayıcıları ayrıntılı bir şekilde incelenerek bunun neden bir sorun olduğu açıklanmaktadır.
Hak sahipleri ve sorumlulukları
Durum bilgisi depolayıcının sorumluluğu, durumu uygulamanın okuyabileceği şekilde depolamaktır. Mantığın gerekli olduğu durumlarda aracı olarak hareket eder ve gerekli mantığı barındıran veri kaynaklarına erişim sağlar. Bu şekilde, durum bilgisi depolayıcı mantığı uygun veri kaynağına devreder.
Bu durum aşağıdaki avantajları sağlar:
- Basit kullanıcı arayüzleri: Kullanıcı arayüzü yalnızca durumunu bağlar.
- Sürdürülebilirlik: Durum bilgisi depolayıcıda tanımlanan mantık, kullanıcı arayüzü değiştirilmeden yinelenebilir.
- Test edilebilirlik: Kullanıcı arayüzü ve durum üretim mantığı bağımsız olarak test edilebilir.
- Okunabilirlik: Kodu okuyanlar, kullanıcı arayüzü sunum kodu ile kullanıcı arayüzü durumu üretim kodu arasındaki farkları net bir şekilde görebilir.
Boyutu veya kapsamı ne olursa olsun her kullanıcı arayüzü öğesi, karşılık gelen durum bilgisi depolayıcısıyla 1:1 ilişkiye sahiptir. Ayrıca, durum bilgisi depolayıcı, kullanıcı arayüzü durum değişikliğine neden olabilecek tüm kullanıcı işlemlerini kabul edip işleyebilmeli ve sonuçtaki durum değişikliğini oluşturmalıdır.
Durum sahibi türleri
Kullanıcı arayüzü durumu ve mantığına benzer şekilde, kullanıcı arayüzü katmanında kullanıcı arayüzü yaşam döngüsüyle ilişkilerine göre tanımlanan iki tür durum tutucu vardır:
- İş mantığı durum tutucusu.
- Kullanıcı arayüzü mantığı durum bilgisi depolayıcısı.
Aşağıdaki bölümlerde, iş mantığı durum bilgisi depolayıcıdan başlayarak durum bilgisi depolayıcı türleri daha ayrıntılı bir şekilde incelenmektedir.
İş mantığı ve durum tutucusu
İş mantığı durum bilgisi depolayıcıları, kullanıcı etkinliklerini işler ve veri katmanlarındaki ya da alan katmanlarındaki verileri ekran kullanıcı arayüzü durumuna dönüştürür. Android yaşam döngüsü ve uygulama yapılandırma değişiklikleri göz önünde bulundurulduğunda en iyi kullanıcı deneyimini sağlamak için iş mantığını kullanan durum tutucular aşağıdaki özelliklere sahip olmalıdır:
| Özellik | Ayrıntı |
|---|---|
| Kullanıcı arayüzü durumu üretir | İş mantığı durumu sahipleri, kullanıcı arayüzleri için kullanıcı arayüzü durumu oluşturmaktan sorumludur. Bu kullanıcı arayüzü durumu genellikle kullanıcı etkinliklerinin işlenmesi ve alan ile veri katmanlarından veri okunması sonucunda ortaya çıkar. |
| Etkinlik yeniden oluşturularak korunur. | İş mantığı durumu sahipleri, Activity yeniden oluşturma sırasında durumlarını ve durum işleme işlem hatlarını koruyarak sorunsuz bir kullanıcı deneyimi sunmaya yardımcı olur. Durum bilgisi depolayıcının korunamadığı ve yeniden oluşturulduğu durumlarda (genellikle işlem sonlandırma sonrasında) tutarlı bir kullanıcı deneyimi sağlamak için durum bilgisi depolayıcı, son durumunu kolayca yeniden oluşturabilmelidir. |
| Uzun süreli duruma sahip olma | İş mantığı durum tutucuları, gezinme hedeflerinin durumunu yönetmek için sıklıkla kullanılır. Bu nedenle, gezinme grafiğinden kaldırılana kadar gezinme değişiklikleri boyunca durumlarını korurlar. |
| Kullanıcı arayüzüne özeldir ve yeniden kullanılamaz. | İş mantığı durum tutucuları genellikle belirli bir uygulama işlevi için durum oluşturur (ör. TaskEditViewModel veya TaskListViewModel) ve bu nedenle yalnızca söz konusu uygulama işlevi için geçerlidir. Aynı durum bilgisi depolayıcı, farklı form faktörlerinde bu uygulama işlevlerini destekleyebilir. Örneğin, uygulamanın mobil, TV ve tablet sürümleri aynı iş mantığı durum tutucusunu yeniden kullanabilir. |
Örneğin, "Now in Android" uygulamasındaki yazar gezinme hedefini ele alalım:
İş mantığı durum bilgisi depolayıcısı olarak hareket eden AuthorViewModel, bu durumda kullanıcı arayüzü durumunu üretir:
@HiltViewModel
class AuthorViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val authorsRepository: AuthorsRepository,
newsRepository: NewsRepository
) : ViewModel() {
val uiState: StateFlow<AuthorScreenUiState> = …
// Business logic
fun followAuthor(followed: Boolean) {
…
}
}
AuthorViewModel öğesinin, daha önce belirtilen özelliklere sahip olduğunu unutmayın:
| Özellik | Ayrıntı |
|---|---|
Üretim: AuthorScreenUiState |
AuthorViewModel, AuthorsRepository ve NewsRepository'den verileri okur ve bu verileri kullanarak AuthorScreenUiState oluşturur. Ayrıca, kullanıcı bir Author'yı takip etmek veya takibi bırakmak istediğinde AuthorsRepository'ya yetki vererek iş mantığını uygular. |
| Veri katmanına erişimi olmalıdır. | Oluşturucusunda AuthorsRepository ve NewsRepository örnekleri geçirilir. Bu sayede, Author takip etme iş mantığını uygulayabilir. |
Activity yeniden oluşturulduğunda bozulmaz |
ViewModel ile uygulandığı için hızlı Activity yeniden oluşturma işleminde korunur. İşlem sonlandığında, kullanıcı arayüzü durumunu veri katmanından geri yüklemek için gereken minimum bilgi miktarını sağlamak üzere SavedStateHandle nesnesi okunabilir. |
| Uzun süreli duruma sahip | ViewModel, gezinme grafiğiyle sınırlıdır. Bu nedenle, yazar hedefi gezinme grafiğinden kaldırılmadığı sürece uiState StateFlow içindeki kullanıcı arayüzü durumu bellekte kalır. StateFlow kullanımı, kullanıcı arayüzü durumu yalnızca kullanıcı arayüzü durumu toplayıcısı varsa üretildiğinden, durumu üreten iş mantığının uygulamasını tembel hale getirme avantajını da sağlar. |
| Kullanıcı arayüzüne özgü olmalıdır. | AuthorViewModel yalnızca yazarın gezinme hedefi için geçerlidir ve başka bir yerde yeniden kullanılamaz. Gezinme hedefleri arasında yeniden kullanılan herhangi bir iş mantığı varsa bu iş mantığı, veri veya alan katmanı kapsamlı bir bileşende kapsüllenmelidir. |
ViewModel'ı iş mantığı durum tutucusu olarak kullanma
Android geliştirmede ViewModel'lerin avantajları, bu bileşenleri iş mantığına erişim sağlamak ve uygulama verilerini ekranda sunulmaya hazırlamak için uygun hale getirir. Bu avantajlar arasında şunlar yer alır:
- ViewModel'ler tarafından tetiklenen işlemler, yapılandırma değişikliklerinden etkilenmez.
- Navigasyon ile entegrasyon:
- Gezinme, ekran eski yığında olduğunda ViewModel'leri önbelleğe alır. Bu, hedefinize döndüğünüzde daha önce yüklediğiniz verilerin anında kullanılabilmesi için önemlidir. Bu, composable ekranın yaşam döngüsünü takip eden bir durum bilgisi depolayıcıyla yapılması daha zor bir işlemdir.
- ViewModel, hedef arka yığından çıkarıldığında da temizlenir. Böylece durumunuzun otomatik olarak temizlenmesi sağlanır. Bu, yeni bir ekrana gitme, yapılandırma değişikliği gibi çeşitli nedenlerle oluşabilen composable öğelerin kaldırılmasını dinlemekten farklıdır.
- Hilt gibi diğer Jetpack kitaplıklarıyla entegrasyon.
Kullanıcı arayüzü mantığı ve durum bilgisi depolayıcısı
Kullanıcı arayüzü mantığı, kullanıcı arayüzünün kendisi tarafından sağlanan veriler üzerinde çalışan mantıktır. Bu, kullanıcı arayüzü öğelerinin durumuna veya izin API'si ya da Resources gibi kullanıcı arayüzü veri kaynaklarına bağlı olabilir. Kullanıcı arayüzü mantığını kullanan durum koruyucular genellikle şu özelliklere sahiptir:
- Kullanıcı arayüzü durumu üretir ve kullanıcı arayüzü öğelerinin durumunu yönetir.
- Yeniden oluşturma işleminden sonra
Activitykorunmaz: Kullanıcı arayüzü mantığında barındırılan durum tutucular genellikle kullanıcı arayüzünün kendisindeki veri kaynaklarına bağlıdır ve bu bilgileri yapılandırma değişiklikleri arasında korumaya çalışmak çoğu zaman bellek sızıntısına neden olur. Durum sahiplerinin yapılandırma değişikliklerinde verilerin kalıcı olması için başka bir bileşene yetki vermesi gerekir. Bu bileşen,Activityyeniden oluşturma işlemine daha uygundur. Örneğin, Jetpack Compose'darememberedişlevleriyle oluşturulan Composable kullanıcı arayüzü öğesi durumları,Activityyeniden oluşturma işlemi sırasında durumu korumak için genelliklerememberSaveable'a devreder. Bu tür işlevlere örnek olarakrememberScaffoldState()verememberLazyListState()verilebilir. - Kullanıcı arayüzü kapsamlı veri kaynaklarına referanslar içerir: Yaşam döngüsü API'leri ve Kaynaklar gibi veri kaynaklarına güvenli bir şekilde referans verilebilir ve bu kaynaklar okunabilir. Bunun nedeni, kullanıcı arayüzü mantık durum bilgisi depolayıcısının kullanıcı arayüzüyle aynı yaşam döngüsüne sahip olmasıdır.
- Birden fazla kullanıcı arayüzünde yeniden kullanılabilir: Aynı kullanıcı arayüzü mantığı durum tutucusunun farklı örnekleri, uygulamanın farklı bölümlerinde yeniden kullanılabilir. Örneğin, bir çip grubu için kullanıcı girişi etkinliklerini yöneten bir durum tutucu, filtre çipleri için bir arama sayfasında ve e-posta alıcılarının "alıcı" alanında kullanılabilir.
Kullanıcı arayüzü mantığı durum bilgisi depolayıcısı genellikle düz bir sınıfla uygulanır. Bunun nedeni, kullanıcı arayüzünün kendisinin kullanıcı arayüzü mantığı durum bilgisi depolayıcısının oluşturulmasından sorumlu olması ve kullanıcı arayüzü mantığı durum bilgisi depolayıcısının, kullanıcı arayüzüyle aynı yaşam döngüsüne sahip olmasıdır. Örneğin, Jetpack Compose'da durum tutucu, Composition'ın bir parçasıdır ve Composition'ın yaşam döngüsünü takip eder.
Yukarıdaki durum, Now in Android örneğindeki aşağıdaki örnekle gösterilebilir:
Now in Android örneği, gezinme için cihazın ekran boyutuna bağlı olarak alt uygulama çubuğu veya gezinme sütunu gösterir. Daha küçük ekranlarda alt uygulama çubuğu, daha büyük ekranlarda ise gezinme rayı kullanılır.
NiaApp composable işlevinde kullanılan uygun gezinme kullanıcı arayüzü öğesine karar verme mantığı iş mantığına bağlı olmadığından NiaAppState adlı düz bir sınıf durum bilgisi depolayıcısı tarafından yönetilebilir:
@Stable
class NiaAppState(
val navController: NavHostController,
val windowSizeClass: WindowSizeClass
) {
// UI logic
val shouldShowBottomBar: Boolean
get() = windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact ||
windowSizeClass.heightSizeClass == WindowHeightSizeClass.Compact
// UI logic
val shouldShowNavRail: Boolean
get() = !shouldShowBottomBar
// UI State
val currentDestination: NavDestination?
@Composable get() = navController
.currentBackStackEntryAsState().value?.destination
// UI logic
fun navigate(destination: NiaNavigationDestination, route: String? = null) { /* ... */ }
/* ... */
}
Yukarıdaki örnekte, NiaAppState ile ilgili aşağıdaki ayrıntılar dikkat çekicidir:
Activityyeniden oluşturma işleminden sonra kalmaz:NiaAppState,rememberediçinde, Compose adlandırma kurallarına uygun olarak bir composable işleviyle oluşturulur.rememberNiaAppStateActivityyeniden oluşturulduktan sonra önceki örnek kaybolur ve tüm bağımlılıkları ile birlikte yeni bir örnek oluşturulur. Bu örnek, yeniden oluşturulanActivity'nın yeni yapılandırması için uygundur. Bu bağımlılıklar yeni olabilir veya önceki yapılandırmadan geri yüklenmiş olabilir. Örneğin,rememberNavController(),NiaAppStateoluşturucusunda kullanılır veActivityyeniden oluşturma işlemi sırasında durumu korumak içinrememberSaveable'ye devreder.- Kullanıcı arayüzü kapsamlı veri kaynaklarına referanslar içeriyor:
navigationController,Resourcesve benzer yaşam döngüsü kapsamlı türlere yapılan referanslar, aynı yaşam döngüsü kapsamını paylaştıkları içinNiaAppStateiçinde güvenle tutulabilir.
Durum tutucu için ViewModel ve düz sınıf arasında seçim yapma
Önceki bölümlerde, ViewModel ile düz bir sınıf durum bilgisi depolayıcısı arasında seçim yapma, kullanıcı arayüzü durumuna uygulanan mantığa ve mantığın üzerinde çalıştığı veri kaynaklarına bağlıdır.
Özetle, aşağıdaki diyagramda durum bilgisi depolayıcıların kullanıcı arayüzündeki konumları gösterilmektedir. Durum oluşturma ardışık düzeni:
Sonuç olarak, kullanıcı arayüzü durumunu, kullanıldığı yere en yakın durum tutucuları kullanarak üretmeniz gerekir. Daha az resmi bir ifadeyle, uygun sahipliği korurken durumu mümkün olduğunca düşük tutmanız gerekir. İşletme mantığına erişmeniz gerekiyorsa ve kullanıcı arayüzü durumunun, ekranlar arasında gezinme sırasında Activity yeniden oluşturulsa bile korunması gerekiyorsa işletme mantığı durum bilgisi depolayıcınızı uygulamak için ViewModel harika bir seçenektir. Daha kısa ömürlü kullanıcı arayüzü durumu ve kullanıcı arayüzü mantığı için yaşam döngüsü yalnızca kullanıcı arayüzüne bağlı olan düz bir sınıf yeterli olmalıdır.
Durum bilgisi depolayıcılar birleştirilebilir
Durum sahipleri, bağımlılıklar eşit veya daha kısa bir kullanım ömrüne sahip olduğu sürece diğer durum sahiplerine bağlı olabilir. Buna örnek olarak aşağıdakiler gösterilebilir:
- Bir kullanıcı arayüzü mantığı durum bilgisi depolayıcısı, başka bir kullanıcı arayüzü mantığı durum bilgisi depolayıcısına bağlı olabilir.
- Ekran düzeyindeki bir durum bilgisi depolayıcı, kullanıcı arayüzü mantığı durum bilgisi depolayıcısına bağlı olabilir.
Aşağıdaki kod snippet'inde, Compose'un DrawerState başka bir dahili durum tutucu olan SwipeableState'a nasıl bağlı olduğu ve bir uygulamanın kullanıcı arayüzü mantığı durum tutucusunun DrawerState'a nasıl bağlı olabileceği gösterilmektedir:
@Stable
class DrawerState(/* ... */) {
internal val swipeableState = SwipeableState(/* ... */)
// ...
}
@Stable
class MyAppState(
private val drawerState: DrawerState,
private val navController: NavHostController
) { /* ... */ }
@Composable
fun rememberMyAppState(
drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
navController: NavHostController = rememberNavController()
): MyAppState = remember(drawerState, navController) {
MyAppState(drawerState, navController)
}
Bir durum bilgisi depolayıcıdan daha uzun süre yaşayan bağımlılık örneği, ekran düzeyinde bir durum bilgisi depolayıcıya bağlı olan bir kullanıcı arayüzü mantığı durum bilgisi depolayıcısı olabilir. Bu durum, daha kısa ömürlü durum bilgisi depolayıcının yeniden kullanılabilirliğini azaltır ve ihtiyaç duyduğundan daha fazla mantığa ve duruma erişmesine neden olur.
Daha kısa ömürlü durum bilgisi depolayıcının daha yüksek kapsamlı bir durum bilgisi depolayıcıdan belirli bilgilere ihtiyacı varsa durum bilgisi depolayıcı örneğini iletmek yerine yalnızca ihtiyaç duyduğu bilgileri parametre olarak iletin. Örneğin, aşağıdaki kod snippet'inde, kullanıcı arayüzü mantığı durum bilgisi depolayıcı sınıfı, bağımlılık olarak ViewModel'in tamamını iletmek yerine ViewModel'den yalnızca ihtiyaç duyduğu parametreleri alır.
class MyScreenViewModel(/* ... */) {
val uiState: StateFlow<MyScreenUiState> = /* ... */
fun doSomething() { /* ... */ }
fun doAnotherThing() { /* ... */ }
// ...
}
@Stable
class MyScreenState(
// DO NOT pass a ViewModel instance to a plain state holder class
// private val viewModel: MyScreenViewModel,
// Instead, pass only what it needs as a dependency
private val someState: StateFlow<SomeState>,
private val doSomething: () -> Unit,
// Other UI-scoped types
private val scaffoldState: ScaffoldState
) {
/* ... */
}
@Composable
fun rememberMyScreenState(
someState: StateFlow<SomeState>,
doSomething: () -> Unit,
scaffoldState: ScaffoldState = rememberScaffoldState()
): MyScreenState = remember(someState, doSomething, scaffoldState) {
MyScreenState(someState, doSomething, scaffoldState)
}
@Composable
fun MyScreen(
modifier: Modifier = Modifier,
viewModel: MyScreenViewModel = viewModel(),
state: MyScreenState = rememberMyScreenState(
someState = viewModel.uiState.map { it.toSomeState() },
doSomething = viewModel::doSomething
),
// ...
) {
/* ... */
}
Aşağıdaki diyagram, kullanıcı arayüzü ile önceki kod snippet'indeki farklı durum bilgisi depolayıcıları arasındaki bağımlılıkları gösterir:
Örnekler
Aşağıdaki Google örneklerinde, kullanıcı arayüzü katmanında durum tutucuların kullanımı gösterilmektedir. Bu kılavuzun nasıl uygulandığını görmek için aşağıdaki kaynakları inceleyin:
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir.
- Kullanıcı arayüzü katmanı
- Kullanıcı arayüzü durumu üretimi
- Uygulama mimarisi kılavuzu