Kullanıcı arayüzünün görevi, uygulama verilerini ekranda göstermektir. Kullanıcı arayüzü, kullanıcı etkileşiminin ana noktası olarak da işlev görür. Kullanıcı etkileşimi (ör. düğmeye basma) veya harici giriş (ör. ağ yanıtı) nedeniyle veriler her değiştiğinde kullanıcı arayüzü bu değişiklikleri yansıtacak şekilde güncellenir. Kullanıcı arayüzü, veri katmanından alınan uygulama durumunun görsel bir temsilidir.
Ancak veri katmanından aldığınız uygulama verileri genellikle görüntülemeniz gereken bilgilerden farklı bir biçimdedir. Örneğin, kullanıcı arayüzü için verilerin yalnızca bir kısmına ihtiyacınız olabilir veya kullanıcıyla alakalı bilgileri sunmak için iki farklı veri kaynağını birleştirmeniz gerekebilir. Uyguladığınız mantık ne olursa olsun, kullanıcı arayüzüne tam olarak oluşturması gereken tüm bilgileri iletmeniz gerekir. Kullanıcı arayüzü katmanı, uygulama verisi değişikliklerini kullanıcı arayüzünün sunabileceği bir forma dönüştürüp görüntüleyen ardışık düzendir.
Temel bir örnek olay
Kullanıcının okuması için haber makaleleri getiren bir uygulama düşünün. Uygulamada, okunabilecek makalelerin gösterildiği bir makaleler ekranı var. Ayrıca oturum açmış kullanıcılar, gerçekten öne çıkan makaleleri yer işaretlerine ekleyebiliyor. Herhangi bir zamanda çok sayıda makale olabileceğinden okuyucu, makalelere kategoriye göre göz atabilmelidir. Özetle, uygulama kullanıcıların şunları yapmasına olanak tanır:
- Okunabilecek makaleleri görüntüleyin.
- Makalelere kategoriye göre göz atın.
- Oturum açıp belirli makaleleri yer işaretlerine ekleyin.
- Uygunsa bazı premium özelliklere erişebilirsiniz.
Aşağıdaki bölümlerde, tek yönlü veri akışı ilkelerini tanıtmak ve bu ilkelerin kullanıcı arayüzü katmanı için uygulama mimarisi bağlamında çözmeye yardımcı olduğu sorunları göstermek amacıyla bu örnek bir örnek olay incelemesi olarak kullanılmaktadır.
Kullanıcı arayüzü katmanı mimarisi
Kullanıcı arayüzü terimi, verileri gösteren kapsayıcılar ve composable işlevler gibi kullanıcı arayüzü öğelerini ifade eder. Android kullanıcı arayüzleri oluşturmak için Jetpack Compose önerilen araç setidir. Veri katmanının rolü, uygulama verilerini tutmak, yönetmek ve bunlara erişim sağlamak olduğundan kullanıcı arayüzü katmanı aşağıdaki adımları uygulamalıdır:
- Uygulama verilerini kullanma ve kullanıcı arayüzünün kolayca oluşturabileceği verilere dönüştürme
- Kullanıcı arayüzünde oluşturulabilir verileri kullanıp bunları kullanıcıya sunmak için kullanıcı arayüzü öğelerine dönüştürür.
- Bu birleştirilmiş kullanıcı arayüzü öğelerinden kullanıcı girişi etkinliklerini kullanın ve bunların etkilerini gerektiği gibi kullanıcı arayüzü verilerine yansıtın.
- 1-3 arasındaki adımları gerektiği kadar tekrarlayın.
Bu kılavuzun geri kalanında, bu adımları uygulayan bir kullanıcı arayüzü katmanının nasıl uygulanacağı gösterilmektedir. Bu kılavuzda özellikle aşağıdaki görevler ve kavramlar ele alınmaktadır:
- Kullanıcı arayüzü durumunu tanımlama
- Kullanıcı arayüzü durumunu oluşturma ve yönetme yöntemi olarak tek yönlü veri akışı (UDF)
- UDF ilkelerine göre gözlemlenebilir veri türleriyle kullanıcı arayüzü durumunu gösterme
- Gözlemlenebilir kullanıcı arayüzü durumunu kullanan bir kullanıcı arayüzü uygulama
Bunların en temeli, kullanıcı arayüzü durumunun tanımıdır.
Kullanıcı arayüzü durumunu tanımlama
Daha önce özetlenen örnek olay incelemesinde kullanıcı arayüzü, her makale için bazı meta verilerle birlikte makalelerin bir listesini gösterir. Uygulamanın kullanıcıya sunduğu bu bilgiler, kullanıcı arayüzü durumudur.
Başka bir deyişle, kullanıcı arayüzü kullanıcının gördüğü şeyse kullanıcı arayüzü durumu, uygulamanın kullanıcının görmesi gerektiğini söylediği şeydir. Aynı madalyonun iki yüzü gibi, kullanıcı arayüzü de kullanıcı arayüzü durumunun görsel temsilidir. Kullanıcı arayüzü durumunda yapılan değişiklikler hemen kullanıcı arayüzüne yansıtılır.
Örnek olay incelemesini ele alalım: Haberler uygulamasının gereksinimlerini karşılamak için kullanıcı arayüzünü tam olarak oluşturmak üzere gereken bilgiler, aşağıdaki gibi tanımlanan bir NewsUiState veri sınıfında kapsüllenebilir:
data class NewsUiState( val isSignedIn: Boolean = false, val isPremium: Boolean = false, val newsItems: List<NewsItemUiState> = listOf(), val userMessages: List<Message> = listOf() ) data class NewsItemUiState( val title: String, val body: String, val bookmarked: Boolean = false, // ... )
Kullanıcı arayüzü durumu hakkında daha fazla bilgi için Durum ve Jetpack Compose başlıklı makaleyi inceleyin.
Değişmezlik
Önceki örnekteki kullanıcı arayüzü durumu tanımı sabittir. Bunun temel avantajı, değişmez nesnelerin uygulamanın belirli bir andaki durumuyla ilgili garanti sağlamasıdır. Bu sayede kullanıcı arayüzü, birincil rolüne odaklanabilir: durumu okumak ve kullanıcı arayüzü öğelerini buna göre güncellemek. Kullanıcı arayüzü, verilerinin tek kaynağı olmadığı sürece kullanıcı arayüzü durumunu doğrudan kullanıcı arayüzünde değiştirmeyin. Bu ilkenin ihlal edilmesi, aynı bilgi parçası için birden fazla doğru kaynağına neden olur. Bu da veri tutarsızlıklarına ve fark edilmesi zor hatalara yol açar.
Örneğin, önceki örnek olay incelemesini ele alalım.
Kullanıcı arayüzü durumundaki bir NewsItemUiState nesnesinde bulunan bookmarked işareti Activity sınıfında güncellenirse bu işaret, bir makalenin yer işareti eklenmiş durumunun kaynağı olarak veri katmanıyla rekabet eder. Değiştirilemez veri sınıfları, bu tür tutarsızlıkları önlemek için çok kullanışlıdır.
Bu kılavuzdaki adlandırma kuralları
Bu kılavuzda, kullanıcı arayüzü durumu sınıfları, tanımladıkları ekranın veya ekranın bir bölümünün işlevine göre adlandırılmıştır. Kural şu şekildedir:
functionality + UiState.
Örneğin, haberlerin gösterildiği bir ekranın durumu NewsUiState, haber öğeleri listesindeki bir haber öğesinin durumu ise NewsItemUiState olarak adlandırılabilir.
Tek yönlü veri akışıyla durumu yönetme
Önceki bölümde, kullanıcı arayüzü durumunun, kullanıcı arayüzünün oluşturulması için gereken ayrıntıların sabit bir anlık görüntüsü olduğu belirtilmişti. Ancak uygulamalardaki verilerin dinamik yapısı, durumun zaman içinde değişebileceği anlamına gelir. Bu durum, kullanıcı etkileşiminden veya uygulamayı doldurmak için kullanılan temel verileri değiştiren diğer etkinliklerden kaynaklanabilir.
Bu etkileşimler, bunları işlemek için bir aracıdan yararlanabilir. Bu aracı, her etkinliğe uygulanacak mantığı tanımlar ve kullanıcı arayüzü durumu oluşturmak için destekleyici veri kaynaklarını dönüştürür. Bu etkileşimler ve mantıkları kullanıcı arayüzünde barındırılabilse de kullanıcı arayüzü çok fazla sorumluluk üstlendiği için bu durum kısa sürede karmaşık hale gelebilir. Ayrıca, sonuçta elde edilen kod sıkı bağlantılı olduğu için test edilebilirliği de etkileyebilir. Kullanıcı arayüzü durumu çok basit değilse kullanıcı arayüzünün tek sorumluluğunun kullanıcı arayüzü durumunu kullanmak ve görüntülemek olduğundan emin olun.
Bu bölümde, bu sağlıklı sorumluluk ayrımını uygulamaya yardımcı olan bir mimari kalıp olan Tek Yönlü Veri Akışı (UDF) ele alınmaktadır.
Durum bilgisi depolayıcılar
Durum bilgisi depolayıcılar, kullanıcı arayüzü durumunu ve bu durumu oluşturmak için gereken mantığı üretmekten sorumlu sınıflardır. Durum bilgisi depolayıcılar, yönettikleri ilgili kullanıcı arayüzü öğelerinin kapsamına bağlı olarak çeşitli boyutlarda olabilir. Bu kapsam, alt uygulama çubuğu gibi tek bir widget'tan tüm ekrana veya gezinme hedefine kadar değişebilir.
İkinci durumda, tipik uygulama bir ViewModel örneğidir ancak uygulamanın gereksinimlerine bağlı olarak basit bir sınıf yeterli olabilir. Örneğin, örnek olay incelemesindeki Haberler uygulaması, ilgili bölümde görüntülenen ekranın kullanıcı arayüzü durumunu oluşturmak için durum bilgisi depolayıcı olarak bir NewsViewModel sınıfı kullanır.
Kullanıcı arayüzü ile durum üreticisi arasındaki karşılıklı bağımlılığı modellemenin birçok yolu vardır. Ancak kullanıcı arayüzü ile ViewModel sınıfı arasındaki etkileşim büyük ölçüde etkinlik girişi ve bunun sonucunda ortaya çıkan durum çıkışı olarak anlaşılabileceğinden, ilişki aşağıdaki şemada gösterildiği gibi temsil edilebilir:
Durumun aşağı, etkinliklerin yukarı doğru aktığı kalıba tek yönlü veri akışı (UDF) denir. Bu kalıbın uygulama mimarisi üzerindeki etkileri şunlardır:
- ViewModel, kullanıcı arayüzü tarafından kullanılacak durumu barındırır ve gösterir. Kullanıcı arayüzü durumu, ViewModel tarafından dönüştürülen uygulama verileridir.
- Kullanıcı arayüzü, kullanıcı etkinliklerini ViewModel'e bildirir.
- ViewModel, kullanıcı işlemlerini işler ve durumu günceller.
- Güncellenen durum, oluşturulmak üzere kullanıcı arayüzüne geri gönderilir.
- Yukarıdaki adımlar, durum mutasyonuna neden olan her etkinlik için tekrarlanır.
ViewModel, gezinme hedefleri veya ekranlar için veri almak ve bu verileri kullanıcı arayüzü durumuna dönüştürmek amacıyla depolarla ya da kullanım alanı sınıflarıyla çalışır. Bu sırada, durumun değişmesine neden olabilecek olayların etkilerini de dahil eder. Daha önce bahsedilen örnek olay incelemesi, her birinin başlığı, açıklaması, kaynağı, yazar adı, yayınlanma tarihi ve yer işaretlerine eklenip eklenmediği bilgisi olan bir makale listesi içerir. Her makale öğesinin kullanıcı arayüzü aşağıdaki gibi görünür:
Bir kullanıcının makaleyi yer işaretlerine ekleme isteği, durum değişikliklerine neden olabilecek bir etkinlik örneğidir. Durum üreticisi olarak ViewModel, kullanıcı arayüzü durumundaki tüm alanları doldurmak için gereken tüm mantığı tanımlamak ve kullanıcı arayüzünün tam olarak oluşturulması için gereken etkinlikleri işlemekle sorumludur.
Aşağıdaki bölümlerde, durum değişikliklerine neden olan etkinlikler ve bunların UDF kullanılarak nasıl işlenebileceği daha ayrıntılı bir şekilde ele alınmaktadır.
Mantık türleri
Bir makaleyi yer işaretlerine eklemek, uygulamanıza değer kattığı için iş mantığına bir örnektir. Bu konuda daha fazla bilgi edinmek için veri katmanı sayfasına bakın. Ancak tanımlanması gereken farklı mantık türleri vardır:
- İş mantığı, uygulama verileri için ürün gereksinimlerinin uygulanmasıdır. Daha önce de belirtildiği gibi, örnek olay incelemesi uygulamasında bir makaleyi yer işaretlerine eklemek buna örnek verilebilir. İş mantığı genellikle alan veya veri katmanlarına yerleştirilir, ancak hiçbir zaman kullanıcı arayüzü katmanına yerleştirilmez.
- Kullanıcı arayüzü davranış mantığı veya kullanıcı arayüzü mantığı, durum değişikliklerinin ekranda nasıl gösterileceğini belirler. Android
Resourceskullanarak ekranda gösterilecek doğru metni alma, kullanıcı bir düğmeyi tıkladığında belirli bir ekrana gitme veya toast ya da snackbar kullanarak ekranda kullanıcı mesajı gösterme bu görevlere örnek verilebilir.
Kullanıcı arayüzü mantığını ViewModel'de değil, kullanıcı arayüzünde tutun. Bu, özellikle Context gibi kullanıcı arayüzü türlerini içerdiğinde önemlidir.
Kullanıcı arayüzü daha karmaşık hale gelirse ve test edilebilirliği ve sorumlulukların ayrılmasını desteklemek için kullanıcı arayüzü mantığını başka bir sınıfa devretmek isterseniz durum bilgisi depolayıcı olarak basit bir sınıf oluşturabilirsiniz. Kullanıcı arayüzünde oluşturulan basit sınıflar, kullanıcı arayüzünün yaşam döngüsünü takip ettikleri için Android SDK bağımlılıklarını alabilir. ViewModel nesnelerinin kullanım ömrü daha uzundur.
Durum bilgisi depolayıcılar ve kullanıcı arayüzü oluşturmaya yardımcı olma bağlamına nasıl uydukları hakkında daha fazla bilgi için Jetpack Compose State kılavuzuna bakın.
UDF'yi neden kullanmalısınız?
UDF, Şekil 4'te gösterildiği gibi durum üretim döngüsünü modeller. Ayrıca durum değişikliklerinin kaynaklandığı, dönüştürüldüğü ve son olarak kullanıldığı yerleri de ayırır. Bu ayrım, kullanıcı arayüzünün tam olarak adının ima ettiği şeyi yapmasını sağlar: durum değişikliklerini gözlemleyerek bilgileri görüntülemek ve bu değişiklikleri ViewModel'e aktararak kullanıcı niyetini iletmek.
Başka bir deyişle, UDF aşağıdakilere olanak tanır:
- Veri tutarlılığı. Kullanıcı arayüzü için tek doğruluk kaynağı vardır.
- Test edilebilirlik. Durum kaynağı izole edildiğinden kullanıcı arayüzünden bağımsız olarak test edilebilir.
- Sürdürülebilirlik. Durumun değişimi, değişimlerin hem kullanıcı etkinliklerinin hem de veri çektikleri kaynakların sonucu olduğu, iyi tanımlanmış bir kalıbı izler.
Kullanıcı arayüzü durumunu gösterme
Kullanıcı arayüzü durumunuzu tanımladıktan ve bu durumun üretimini nasıl yöneteceğinizi belirledikten sonraki adım, üretilen durumu kullanıcı arayüzüne sunmaktır.
Durum üretimini yönetmek için UDF kullanırken üretilen durumu bir akış olarak düşünebilirsiniz. Diğer bir deyişle, zaman içinde durumun birden fazla sürümü üretilir. Kullanıcı arayüzü durumunu StateFlow gibi gözlemlenebilir bir veri tutucuda gösterin. Bu sayede kullanıcı arayüzü, verileri doğrudan ViewModel'den manuel olarak çekmek zorunda kalmadan durumda yapılan değişikliklere tepki verebilir. Bu sayede, kullanıcı arayüzü durumunun en yeni sürümü her zaman önbelleğe alınır. Bu da yapılandırma değişikliklerinden sonra durumun hızlı bir şekilde geri yüklenmesi için kullanışlıdır.
class NewsViewModel( // ... ) : ViewModel() { val uiState: NewsUiState = /* ... */ }
Kotlin akışlarına giriş için Android'de Kotlin akışları başlıklı makaleyi inceleyin.
StateFlow sınıfını gözlemlenebilir bir veri tutucu olarak nasıl kullanacağınızı öğrenmek için Jetpack Compose'da Advanced State ve Yan Etkiler codelab'ini inceleyin.
Kullanıcı arayüzüne sunulan verilerin nispeten basit olduğu durumlarda, durum bilgisi depolayıcının yayını ile ilişkili ekranı veya kullanıcı arayüzü öğesi arasındaki ilişkiyi aktardığı için verileri bir kullanıcı arayüzü durumu türüne sarmalamak genellikle faydalıdır. Kullanıcı arayüzü öğesi daha karmaşık hale geldikçe kullanıcı arayüzü durumunun tanımına ekleme yapmak kolaydır. Böylece, kullanıcı arayüzü öğesini oluşturmak için gereken ek bilgileri barındırabilirsiniz.
UiState akışı oluşturmanın yaygın bir yolu, private set ile bir mutableStateOf mülkü göstererek durumu ViewModel içinde değiştirilebilir ancak kullanıcı arayüzü için salt okunur olarak tutmaktır.
class NewsViewModel( // ... ) : ViewModel() { var uiState by mutableStateOf(NewsUiState()) private set // ... }
Ardından ViewModel, durumu dahili olarak değiştiren yöntemleri kullanıma sunarak kullanıcı arayüzünün kullanacağı güncellemeleri yayınlayabilir. Örneğin, eşzamansız bir işlem yapmanız gerektiğini varsayalım.
viewModelScope kullanarak bir eş yordam başlatabilir ve tamamlandığında değiştirilebilir durumu güncelleyebilirsiniz.
class NewsViewModel( private val repository: NewsRepository, // ... ) : ViewModel() { var uiState by mutableStateOf(NewsUiState()) private set private var fetchJob: Job? = null fun fetchArticles(category: String) { fetchJob?.cancel() fetchJob = viewModelScope.launch { try { val newsItems = repository.newsItemsForCategory(category) uiState = uiState.copy(newsItems = newsItems) } catch (ioe: IOException) { // Handle the error and notify the UI when appropriate. val messages = getMessagesFromThrowable(ioe) uiState = uiState.copy(userMessages = messages) } } } }
Yukarıdaki örnekte NewsViewModel sınıfı, belirli bir kategori için makaleleri getirmeye çalışır ve ardından denemenin sonucunu (başarılı veya başarısız) kullanıcı arayüzü durumuna yansıtır. Kullanıcı arayüzü de buna uygun şekilde tepki verebilir.
Hataların ele alınması hakkında daha fazla bilgi için Hataları ekranda gösterme bölümüne göz atın.
Göz önünde bulundurulacak diğer noktalar
Önceki kılavuza ek olarak, kullanıcı arayüzü durumunu gösterirken aşağıdakileri göz önünde bulundurun:
Birbiriyle ilişkili durumları işlemek için tek bir kullanıcı arayüzü durumu nesnesi kullanın. Bu sayede tutarsızlıklar azalır ve kodun anlaşılması kolaylaşır. Haber öğelerinin listesini ve yer işaretlerinin sayısını iki farklı akışta gösterirseniz birinin güncellenip diğerinin güncellenmediği bir durumla karşılaşabilirsiniz. Tek bir akış kullandığınızda her iki öğe de güncel tutulur. Ayrıca bazı iş mantıkları, kaynakların bir kombinasyonunu gerektirebilir. Örneğin, yer işareti düğmesini yalnızca kullanıcı oturum açmışsa ve ücretli bir haber hizmetine abone olmuşsa göstermeniz gerekebilir. Kullanıcı arayüzü durum sınıfını aşağıdaki gibi tanımlayabilirsiniz:
data class NewsUiState( val isSignedIn: Boolean = false, val isPremium: Boolean = false, val newsItems: List<NewsItemUiState> = listOf() ) val NewsUiState.canBookmarkNews: Boolean get() = isSignedIn && isPremium
Bu beyanda, yer işareti düğmesinin görünürlüğü diğer iki özelliğin türetilmiş bir özelliğidir. İş mantığı karmaşıklaştıkça tüm özelliklerin hemen kullanılabildiği tek bir
UiStatesınıfına sahip olmak giderek daha önemli hale gelir.Kullanıcı arayüzü durumları: tek akış mı yoksa birden fazla akış mı? Kullanıcı arayüzü durumunu tek bir akışta veya birden fazla akışta gösterme arasında seçim yaparken yol gösterici temel ilke, yayınlanan öğeler arasındaki ilişkidir. Tek akışlı durumun en büyük avantajları, kolaylık ve veri tutarlılığıdır. Durumun tüketicileri, her zaman en güncel bilgilere erişebilir. Ancak ViewModel'den ayrı durum akışlarının uygun olabileceği durumlar da vardır:
İlişkisiz veri türleri: Kullanıcı arayüzünü oluşturmak için gereken bazı durumlar birbirinden tamamen bağımsız olabilir. Bu gibi durumlarda, özellikle de durumlardan biri diğerinden daha sık güncelleniyorsa bu farklı durumları bir araya getirmenin maliyeti, faydalarından daha fazla olabilir.
UiStatefarkı: BirUiStatenesnesinde ne kadar çok alan varsa akışın, alanlarından birinin güncellenmesi sonucunda yayınlanma olasılığı o kadar artar. Kullanıcı arayüzü öğelerinde, ardışık emisyonların farklı mı yoksa aynı mı olduğunu anlamak için bir fark mekanizması olmadığından her emisyon, kullanıcı arayüzü öğesinin güncellenmesine neden olur. Bu nedenle,distinctUntilChanged()gibiFlowAPI yöntemlerini kullanarak risk azaltma işlemi yapmanız gerekebilir.
Oluşturma ve kullanıcı arayüzü durumu hakkında daha fazla bilgi için Birleştirilebilir öğelerin yaşam döngüsü başlıklı makaleyi inceleyin.
Kullanıcı arayüzü durumunu kullanma
Kullanıcı arayüzündeki UiState nesnelerinin akışını kullanmak için kullandığınız gözlemlenebilir veri türünün terminal operatörünü kullanın. Örneğin, Kotlin akışları için collect() yöntemini veya varyasyonlarını kullanın.
Kullanıcı arayüzünde gözlemlenebilir veri tutucuları kullanırken kullanıcı arayüzünün yaşam döngüsünü göz önünde bulundurun. Composable kullanıcıya gösterilmediğinde kullanıcı arayüzünün, kullanıcı arayüzü durumunu gözlemlemesine izin vermeyin. Bu konu hakkında daha fazla bilgi edinmek için bu blog yayınını inceleyin. Akışları kullanırken yaşam döngüsüyle ilgili sorunları uygun eş yordam kapsamı ve collectAsStateWithLifecycle API'si ile ele almak en iyisidir:
@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) /* ... */ }
Devam eden işlemleri göster
Yükleme durumlarını bir UiState sınıfında temsil etmenin basit bir yolu, boole alanı kullanmaktır:
data class NewsUiState( val isFetchingArticles: Boolean = false, // ... )
Bu işaretin değeri, kullanıcı arayüzünde ilerleme çubuğunun olup olmadığını gösterir.
@Composable fun LatestNewsScreen( modifier: Modifier = Modifier, viewModel: NewsViewModel = viewModel() ) { Box(modifier.fillMaxSize()) { if (viewModel.uiState.isFetchingArticles) { CircularProgressIndicator(Modifier.align(Alignment.Center)) } // Add other UI elements. For example, the list. } }
Hataları ekranda göster
Kullanıcı arayüzünde hataları göstermek, devam eden işlemleri göstermeye benzer. Çünkü her ikisi de varlıklarını veya yokluklarını belirten boole değerleriyle kolayca temsil edilir. Ancak hatalar, kullanıcıya geri iletilecek ilişkili bir mesaj veya başarısız işlemi yeniden deneyen ilişkili bir işlem de içerebilir. Bu nedenle, devam eden bir işlem yüklenirken veya yüklenmezken hata durumlarının, hatanın bağlamına uygun meta verileri barındıran veri sınıflarıyla modellenmesi gerekebilir.
Makaleler getirilirken ilerleme çubuğu gösteren önceki örneği ele alalım. Bu işlem bir hatayla sonuçlanırsa kullanıcıya neyin yanlış gittiğini ayrıntılı olarak açıklayan bir veya daha fazla mesaj göstermek isteyebilirsiniz.
data class Message(val id: Long, val message: String) data class NewsUiState( val userMessages: List<Message> = listOf(), // ... )
Ardından, hata mesajlarını kullanıcıya snackbar gibi kullanıcı arayüzü öğeleri biçiminde sunabilirsiniz. Kullanıcı arayüzü etkinliklerinin nasıl oluşturulduğu ve kullanıldığı hakkında daha fazla bilgi için Kullanıcı arayüzü etkinlikleri başlıklı makaleyi inceleyin.
İş parçacığı oluşturma ve eşzamanlılık
ViewModel'de gerçekleştirilen tüm çalışmaların ana iş parçacığı için güvenli (ana iş parçacığından çağrılması güvenli) olduğundan emin olun. Veri ve alan katmanları, işi farklı bir iş parçacığına taşımaktan sorumludur.
ViewModel uzun süreli işlemler gerçekleştiriyorsa bu mantığı bir arka plan iş parçacığına taşımaktan da sorumludur. Kotlin eş yordamları, eşzamanlı işlemleri yönetmek için harika bir yöntemdir ve Jetpack Mimari Bileşenleri, eş yordamlar için yerleşik destek sunar. Android uygulamalarında eş yordamları kullanma hakkında daha fazla bilgi edinmek için Android'de Kotlin eş yordamları başlıklı makaleyi inceleyin.
Gezinme
Uygulama gezinmesindeki değişiklikler genellikle etkinlik benzeri emisyonlardan kaynaklanır. Örneğin, bir SignInViewModel sınıfı oturum açma işlemi gerçekleştirdikten sonra UiState, true olarak ayarlanmış bir isSignedIn alanına sahip olabilir. Bu tür tetikleyicileri, daha önceki Kullanıcı arayüzü durumunu kullanma bölümünde ele alınanlar gibi kullanın ancak kullanım uygulamasını Gezinme bileşenine erteleyin.
Kullanıcı arayüzünde gezinme hakkında daha fazla bilgi için Gezinme 3 bölümüne bakın.
Sayfalandırma
Paging kitaplığı, kullanıcı arayüzünde PagingData adlı bir türle kullanılır. PagingData, zaman içinde değişebilen öğeleri temsil ettiğinden ve içerdiğinden (yani sabit bir tür olmadığından) sabit bir kullanıcı arayüzü durumunda temsil etmeyin.
Bunun yerine, ViewModel'den bağımsız olarak kendi akışında gösterin.
Aşağıdaki örnekte, Paging kitaplığının Compose API'si gösterilmektedir:
@Composable fun MyScreen(flow: Flow<PagingData<String>>) { val lazyPagingItems = flow.collectAsLazyPagingItems() LazyColumn { items( lazyPagingItems.itemCount, key = lazyPagingItems.itemKey { it } ) { index -> val item = lazyPagingItems[index] Text("Item is $item") } } }
Animasyonlar
Üst düzey gezinme geçişlerinin sorunsuz olması için animasyonu başlatmadan önce ikinci ekranın verileri yüklemesini bekleyebilirsiniz.
Gezinme geçişleri hakkında daha fazla bilgi için Navigation 3 ve Compose'da paylaşılan öğe geçişleri başlıklı makaleleri inceleyin.
Ek kaynaklar
İçerik görüntüleme
Örnekler
Aşağıdaki Google örnekleri, kullanıcı arayüzü katmanının kullanımını göstermektedir. Bu kılavuzun pratikteki işleyişini görmek için bu kaynakları inceleyin:
Sizin için önerilenler
- Not: JavaScript devre dışı bırakıldığında bağlantı metni gösterilir.
- Kullanıcı arayüzü durum üretimi
- Durum bilgisi depolayıcılar ve kullanıcı arayüzü durumu {:#mad-arch}
- Uygulama mimarisi kılavuzu