Kavramlar ve Jetpack Compose uygulaması
Kullanıcı arayüzünün rolü, uygulama verilerini ekranda göstermenin yanı sıra kullanıcının etkileşim kurduğu birincil nokta olarak hizmet etmektir. Veriler, kullanıcı etkileşimi (ör. düğmeye basma) veya harici giriş (ör. ağ yanıtı) nedeniyle her değiştiğinde kullanıcı arayüzü, bu değişiklikleri yansıtacak şekilde güncellenmelidir. 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ıktan bağımsız olarak, kullanıcı arayüzüne tam olarak oluşturulması için gereken tüm bilgileri iletmeniz gerekir. Kullanıcı arayüzü katmanı, uygulama verilerindeki değişiklikleri kullanıcı arayüzünün sunabileceği bir forma dönüştüren ve ardından görüntüleyen ardışık düzendir.
Kullanıcı arayüzü durumunu kullanıma sunma
Kullanıcı arayüzü durumunuzu tanımlayıp bu durumun üretimini nasıl yöneteceğinizi belirledikten sonraki adım, üretilen durumu kullanıcı arayüzünde göstermektir. Durum üretimini yönetmek için UDF kullandığınızdan, üretilen durumu bir akış olarak düşünebilirsiniz. Diğer bir deyişle, zaman içinde durumun birden fazla sürümü üretilir. Bu nedenle, kullanıcı arayüzü durumunu LiveData veya StateFlow gibi gözlemlenebilir bir veri tutucuda göstermeniz gerekir. Bunun nedeni, kullanıcı arayüzünün, verileri doğrudan ViewModel'den manuel olarak çekmek zorunda kalmadan durumdaki değişikliklere tepki verebilmesidir. Bu türler, kullanıcı arayüzü durumunun her zaman en son sürümünün önbelleğe alınması avantajına da sahiptir. Bu, yapılandırma değişikliklerinden sonra durumun hızlı bir şekilde geri yüklenmesi için yararlıdır.
class NewsViewModel(...) : ViewModel() {
val uiState: StateFlow<NewsUiState> = …
}
UiState akışı oluşturmanın yaygın bir yolu, ViewModel'den destekleyen değiştirilebilir bir akışı değiştirilemez bir akış olarak kullanıma sunmaktır. Örneğin, MutableStateFlow<UiState> öğesini StateFlow<UiState> olarak kullanıma sunma.
class NewsViewModel(...) : ViewModel() {
private val _uiState = MutableStateFlow(NewsUiState())
val uiState: StateFlow<NewsUiState> = _uiState.asStateFlow()
...
}
ViewModel daha sonra durumu dahili olarak değiştiren yöntemleri kullanıma sunabilir ve kullanıcı arayüzünün kullanması için güncellemeler yayınlayabilir. Örneğin, eşzamansız bir işlemin yapılması gerektiği durumu ele alalım. viewModelScope kullanılarak bir eş yordam başlatılabilir ve işlem tamamlandığında değiştirilebilir durum güncellenebilir.
class NewsViewModel(
private val repository: NewsRepository,
...
) : ViewModel() {
private val _uiState = MutableStateFlow(NewsUiState())
val uiState: StateFlow<NewsUiState> = _uiState.asStateFlow()
private var fetchJob: Job? = null
fun fetchArticles(category: String) {
fetchJob?.cancel()
fetchJob = viewModelScope.launch {
try {
val newsItems = repository.newsItemsForCategory(category)
_uiState.update {
it.copy(newsItems = newsItems)
}
} catch (ioe: IOException) {
// Handle the error and notify the UI when appropriate.
_uiState.update {
val messages = getMessagesFromThrowable(ioe)
it.copy(userMessages = messages)
}
}
}
}
}
Kullanıcı arayüzü durumunu kullanma
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 bulundurduğunuzdan emin olun. Bu önemlidir, çünkü görünüm kullanıcıya gösterilmediğinde kullanıcı arayüzü, kullanıcı arayüzü durumunu gözlemlememelidir. Bu konu hakkında daha fazla bilgi edinmek için bu blog yayınını inceleyin.
LiveData kullanılırken LiveData, yaşam döngüsüyle ilgili sorunları örtülü olarak ele alır.LifecycleOwner Akışları kullanırken bunu uygun repeatOnLifecycle API'si ve uygun coroutine kapsamıyla ele almak en iyisidir:
class NewsActivity : AppCompatActivity() {
private val viewModel: NewsViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
...
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
// Update UI elements
}
}
}
}
}
Devam eden işlemleri göster
UiState sınıfında yükleme durumlarını temsil etmenin basit bir yolu, boolean 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.
class NewsActivity : AppCompatActivity() {
private val viewModel: NewsViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
...
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
// Bind the visibility of the progressBar to the state
// of isFetchingArticles.
viewModel.uiState
.map { it.isFetchingArticles }
.distinctUntilChanged()
.collect { progressBar.isVisible = it }
}
}
}
}
Animasyonlar
Akıcı ve sorunsuz üst düzey gezinme geçişleri sağlamak için animasyonu başlatmadan önce ikinci ekranın verileri yüklemesini bekleyebilirsiniz.
Android görünüm çerçevesi, postponeEnterTransition() ve startPostponedEnterTransition() API'leri ile parça hedefleri arasındaki geçişleri geciktirmek için kancalar sağlar. Bu API'ler, ikinci ekrandaki kullanıcı arayüzü öğelerinin (genellikle ağdan getirilen bir resim) kullanıcı arayüzü bu ekrana geçişi canlandırmadan önce görüntülenmeye hazır olmasını sağlamanın bir yolunu sunar.
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir.
- Kullanıcı arayüzü durumu üretimi
- Durum tutucular ve kullanıcı arayüzü durumu {:#mad-arch}
- Uygulama mimarisi kılavuzu