सिद्धांत और Jetpack Compose में लागू करना
यूज़र इंटरफ़ेस (यूआई) का काम, स्क्रीन पर ऐप्लिकेशन का डेटा दिखाना है. साथ ही, यह उपयोगकर्ता के इंटरैक्शन का मुख्य पॉइंट भी होता है. जब भी डेटा में बदलाव होता है, तो यूज़र इंटरफ़ेस (यूआई) को अपडेट होना चाहिए, ताकि उन बदलावों को दिखाया जा सके. डेटा में बदलाव, उपयोगकर्ता के इंटरैक्शन (जैसे, बटन दबाना) या बाहरी इनपुट (जैसे, नेटवर्क रिस्पॉन्स) की वजह से हो सकता है. असल में, यूज़र इंटरफ़ेस (यूआई), ऐप्लिकेशन की स्थिति को विज़ुअल तौर पर दिखाता है. यह स्थिति, डेटा लेयर से मिलती है.
हालांकि, डेटा लेयर से मिलने वाला ऐप्लिकेशन डेटा आम तौर पर, उस जानकारी से अलग फ़ॉर्मैट में होता है जिसे आपको दिखाना है. उदाहरण के लिए, ऐसा हो सकता है कि आपको यूज़र इंटरफ़ेस (यूआई) के लिए सिर्फ़ डेटा के कुछ हिस्से की ज़रूरत हो. इसके अलावा, ऐसा भी हो सकता है कि आपको उपयोगकर्ता के लिए काम की जानकारी दिखाने के लिए, दो अलग-अलग डेटा सोर्स को मर्ज करना पड़े. आपने जो भी लॉजिक इस्तेमाल किया है उससे कोई फ़र्क़ नहीं पड़ता. आपको यूज़र इंटरफ़ेस (यूआई) को वह सारी जानकारी देनी होगी जो उसे पूरी तरह से रेंडर करने के लिए ज़रूरी है. यूज़र इंटरफ़ेस (यूआई) लेयर, एक ऐसी पाइपलाइन होती है जो ऐप्लिकेशन के डेटा में हुए बदलावों को ऐसे फ़ॉर्म में बदलती है जिसे यूज़र इंटरफ़ेस (यूआई) दिखा सके. इसके बाद, यह उसे दिखाती है.
यूज़र इंटरफ़ेस (यूआई) की स्थिति को सार्वजनिक करना
यूज़र इंटरफ़ेस (यूआई) की स्थिति तय करने और यह तय करने के बाद कि उस स्थिति को कैसे मैनेज किया जाएगा, अगला चरण यूज़र इंटरफ़ेस (यूआई) को उस स्थिति के बारे में बताना है. स्टेट के प्रोडक्शन को मैनेज करने के लिए, यूडीएफ़ का इस्तेमाल किया जा रहा है. इसलिए, प्रोड्यूस की गई स्टेट को स्ट्रीम माना जा सकता है. दूसरे शब्दों में कहें, तो समय के साथ स्टेट के कई वर्शन प्रोड्यूस किए जाएंगे. इसलिए, आपको यूज़र इंटरफ़ेस (यूआई) की स्थिति को LiveData या StateFlow जैसे ऑब्ज़र्वेबल डेटा होल्डर में दिखाना चाहिए. ऐसा इसलिए किया जाता है, ताकि यूज़र इंटरफ़ेस (यूआई), ViewModel से डेटा को मैन्युअल तरीके से सीधे तौर पर पुल किए बिना, स्थिति में किए गए किसी भी बदलाव पर प्रतिक्रिया कर सके. इन टाइप के फ़ायदे यह भी हैं कि इनके पास हमेशा यूज़र इंटरफ़ेस (यूआई) की स्थिति का सबसे नया वर्शन कैश मेमोरी में सेव होता है. यह कॉन्फ़िगरेशन में बदलाव के बाद, स्थिति को तुरंत पहले जैसा करने के लिए फ़ायदेमंद होता है.
class NewsViewModel(...) : ViewModel() {
val uiState: StateFlow<NewsUiState> = …
}
UiState की स्ट्रीम बनाने का एक सामान्य तरीका यह है कि ViewModel से, बैकअप लेने वाली स्ट्रीम को नहीं बदली जा सकने वाली स्ट्रीम के तौर पर दिखाया जाए. उदाहरण के लिए, MutableStateFlow<UiState> को StateFlow<UiState> के तौर पर दिखाना.
class NewsViewModel(...) : ViewModel() {
private val _uiState = MutableStateFlow(NewsUiState())
val uiState: StateFlow<NewsUiState> = _uiState.asStateFlow()
...
}
इसके बाद, ViewModel ऐसे तरीके दिखा सकता है जो अंदरूनी तौर पर स्थिति में बदलाव करते हैं. साथ ही, यूज़र इंटरफ़ेस (यूआई) के इस्तेमाल के लिए अपडेट पब्लिश करते हैं. उदाहरण के लिए, मान लें कि किसी एसिंक्रोनस कार्रवाई को पूरा करना है. इसके लिए, viewModelScope का इस्तेमाल करके कोरूटीन लॉन्च किया जा सकता है. साथ ही, कार्रवाई पूरी होने पर बदलाव किए जा सकने वाले स्टेटस को अपडेट किया जा सकता है.
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)
}
}
}
}
}
यूज़र इंटरफ़ेस (यूआई) की स्थिति का इस्तेमाल करना
यूज़र इंटरफ़ेस (यूआई) में ऑब्ज़र्वेबल डेटा होल्डर का इस्तेमाल करते समय, पक्का करें कि आपने यूज़र इंटरफ़ेस (यूआई) के लाइफ़साइकल को ध्यान में रखा हो. यह इसलिए ज़रूरी है, क्योंकि जब व्यू उपयोगकर्ता को नहीं दिख रहा होता है, तब यूज़र इंटरफ़ेस (यूआई) को यूआई की स्थिति पर नज़र नहीं रखनी चाहिए. इस विषय के बारे में ज़्यादा जानने के लिए, यह ब्लॉग पोस्ट पढ़ें.
LiveData का इस्तेमाल करते समय, LifecycleOwner लाइफ़साइकल से जुड़ी समस्याओं का ध्यान रखता है. फ़्लो का इस्तेमाल करते समय, इस समस्या को सही को-रूटीन स्कोप और repeatOnLifecycle एपीआई की मदद से हल करना सबसे सही तरीका है:
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
}
}
}
}
}
चल रही कार्रवाइयां दिखाएं
UiState क्लास में लोडिंग की स्थितियां दिखाने का आसान तरीका, बूलियन फ़ील्ड का इस्तेमाल करना है:
data class NewsUiState(
val isFetchingArticles: Boolean = false,
...
)
इस फ़्लैग की वैल्यू से पता चलता है कि यूज़र इंटरफ़ेस (यूआई) में प्रोग्रेस बार मौजूद है या नहीं.
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 }
}
}
}
}
ऐनिमेशन
टॉप-लेवल नेविगेशन ट्रांज़िशन को फ़्लूड और स्मूद बनाने के लिए, आपको ऐनिमेशन शुरू करने से पहले दूसरी स्क्रीन के डेटा लोड होने का इंतज़ार करना पड़ सकता है.
Android व्यू फ़्रेमवर्क, postponeEnterTransition() और startPostponedEnterTransition() API की मदद से, फ़्रैगमेंट डेस्टिनेशन के बीच ट्रांज़िशन में देरी करने के लिए हुक उपलब्ध कराता है. इन एपीआई की मदद से, यह पक्का किया जा सकता है कि दूसरी स्क्रीन पर मौजूद यूज़र इंटरफ़ेस (यूआई) एलिमेंट (आम तौर पर, नेटवर्क से फ़ेच की गई इमेज) दिखाने के लिए तैयार हैं. ऐसा तब होता है, जब यूज़र इंटरफ़ेस (यूआई) उस स्क्रीन पर ट्रांज़िशन को ऐनिमेट करता है.
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक का टेक्स्ट दिखता है
- यूज़र इंटरफ़ेस (यूआई) स्टेट प्रोडक्शन
- स्टेट होल्डर और यूज़र इंटरफ़ेस (यूआई) स्टेट {:#mad-arch}
- ऐप्लिकेशन के आर्किटेक्चर की गाइड