ऐप्लिकेशन में स्टेट, ऐसी वैल्यू होती है जो समय के साथ बदल सकती है. यह एक बहुत व्यापक परिभाषा है. इसमें Room डेटाबेस से लेकर क्लास में मौजूद वैरिएबल तक सब कुछ शामिल है.
सभी Android ऐप्लिकेशन, उपयोगकर्ता को स्थिति दिखाते हैं. Android ऐप्लिकेशन में स्थिति के कुछ उदाहरण:
- यह स्नैकबार तब दिखता है, जब नेटवर्क कनेक्शन नहीं हो पाता.
- ब्लॉग पोस्ट और उससे जुड़ी टिप्पणियां.
- बटन पर रिपल एनिमेशन, जो उपयोगकर्ता के क्लिक करने पर चलते हैं.
- ऐसे स्टिकर जिन्हें उपयोगकर्ता किसी इमेज के ऊपर बना सकता है.
Jetpack Compose की मदद से, Android ऐप्लिकेशन में स्टेट को सेव करने और इस्तेमाल करने के तरीके के बारे में साफ़ तौर पर बताया जा सकता है. इस गाइड में, स्टेट और कंपोज़ेबल के बीच के कनेक्शन के बारे में बताया गया है. साथ ही, उन एपीआई के बारे में बताया गया है जो Jetpack Compose, स्टेट के साथ काम करने के लिए उपलब्ध कराता है.
स्थिति और कंपोज़िशन
Compose, डिक्लेरेटिव है. इसलिए, इसे अपडेट करने का सिर्फ़ एक तरीका है. इसके लिए, नए आर्ग्युमेंट के साथ उसी कंपोज़ेबल को कॉल करना होगा. ये आर्ग्युमेंट, यूज़र इंटरफ़ेस (यूआई) की स्थिति को दिखाते हैं. जब भी किसी स्टेट को अपडेट किया जाता है, तब recomposition होता है. इस वजह से, TextField जैसी चीज़ें अपने-आप अपडेट नहीं होती हैं. हालांकि, ये ज़रूरी एक्सएमएल पर आधारित व्यू में अपने-आप अपडेट हो जाती हैं. कंपोज़ेबल को नई स्थिति के बारे में साफ़ तौर पर बताना होगा, ताकि वह उसके हिसाब से अपडेट हो सके.
@Composable private fun HelloContent() { Column(modifier = Modifier.padding(16.dp)) { Text( text = "Hello!", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) OutlinedTextField( value = "", onValueChange = { }, label = { Text("Name") } ) } }
इसे चलाने और टेक्स्ट डालने की कोशिश करने पर, आपको दिखेगा कि कुछ नहीं हो रहा है. ऐसा इसलिए होता है, क्योंकि TextField अपने-आप अपडेट नहीं होता. यह तब अपडेट होता है, जब इसके value पैरामीटर में बदलाव होता है. ऐसा इसलिए होता है, क्योंकि Compose में कंपोज़िशन और रीकंपोज़िशन का तरीका अलग होता है.
शुरुआती कंपोज़िशन: कंपोज़ेबल को पहली बार चलाने पर कंपोज़िशन बनती है.
रीकंपोज़िशन: डेटा में बदलाव होने पर, कंपोज़िशन को अपडेट करने के लिए कंपोज़ेबल को फिर से चलाना.
शुरुआती कंपोज़िशन और रीकंपोज़िशन के बारे में ज़्यादा जानने के लिए, Compose के बारे में सोचना लेख पढ़ें.
कंपोज़ेबल में स्टेट
कंपोज़ेबल फ़ंक्शन, remember एपीआई का इस्तेमाल करके, किसी ऑब्जेक्ट को मेमोरी में सेव कर सकते हैं. remember से कैलकुलेट की गई वैल्यू को कंपोज़िशन के दौरान कंपोज़िशन में सेव किया जाता है. इसके बाद, रिकलकुलेट करने के दौरान सेव की गई वैल्यू को वापस लाया जाता है. remember का इस्तेमाल, बदले जा सकने वाले और नहीं बदले जा सकने वाले, दोनों ऑब्जेक्ट को सेव करने के लिए किया जा सकता है.
mutableStateOf एक observable MutableState<T> बनाता है, जो कंपोज़ रनटाइम के साथ इंटिग्रेट किया गया एक observable टाइप है.
interface MutableState<T> : State<T> {
override var value: T
}
value में किए गए किसी भी बदलाव से, value को पढ़ने वाले किसी भी कंपोज़ेबल फ़ंक्शन के शेड्यूल को फिर से कंपोज़ किया जाएगा.
कंपोज़ेबल में MutableState ऑब्जेक्ट को तीन तरीकों से एलान किया जा सकता है:
val mutableState = remember { mutableStateOf(default) }var value by remember { mutableStateOf(default) }val (value, setValue) = remember { mutableStateOf(default) }
ये घोषणाएं एक जैसी हैं और स्टेट के अलग-अलग इस्तेमाल के लिए सिंटैक्स शुगर के तौर पर दी गई हैं. आपको ऐसा कोड चुनना चाहिए जिसे कंपोज़ेबल में आसानी से पढ़ा जा सके.
by डेलिगेट सिंटैक्स के लिए, यहां दिए गए इंपोर्ट की ज़रूरत होती है:
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
याद रखी गई वैल्यू का इस्तेमाल, अन्य कंपोज़ेबल के लिए पैरामीटर के तौर पर किया जा सकता है. इसके अलावा, इसका इस्तेमाल स्टेटमेंट में लॉजिक के तौर पर भी किया जा सकता है, ताकि यह बदला जा सके कि कौनसे कंपोज़ेबल दिखाए जाएं. उदाहरण के लिए, अगर नाम खाली होने पर आपको बधाई नहीं दिखानी है, तो if स्टेटमेंट में स्थिति का इस्तेमाल करें:
@Composable fun HelloContent() { Column(modifier = Modifier.padding(16.dp)) { var name by remember { mutableStateOf("") } if (name.isNotEmpty()) { Text( text = "Hello, $name!", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) } OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Name") } ) } }
remember की मदद से, रीकंपोज़िशन के दौरान स्थिति को बनाए रखा जा सकता है. हालांकि, कॉन्फ़िगरेशन में बदलाव होने पर स्थिति को बनाए नहीं रखा जाता. इसके लिए, आपको rememberSaveable का इस्तेमाल करना होगा. rememberSaveable में सेव की जा सकने वाली किसी भी वैल्यू को Bundle अपने-आप सेव कर लेता है. अन्य वैल्यू के लिए, कस्टम सेवर ऑब्जेक्ट पास किया जा सकता है.
स्टेट के अन्य टाइप, जिनके साथ काम किया जा सकता है
Compose में, स्थिति को बनाए रखने के लिए MutableState<T> का इस्तेमाल करना ज़रूरी नहीं है. यह अन्य ऑब्ज़र्वेबल टाइप के साथ काम करता है. Compose में किसी दूसरे ऑब्ज़र्वेबल टाइप को पढ़ने से पहले, आपको उसे State<T> में बदलना होगा. इससे, स्थिति में बदलाव होने पर कंपोज़ेबल अपने-आप फिर से कंपोज़ हो सकते हैं.
Compose में, Android ऐप्लिकेशन में इस्तेमाल होने वाले सामान्य ऑब्ज़र्वेबल टाइप से State<T> बनाने के लिए फ़ंक्शन शामिल होते हैं. इन इंटिग्रेशन का इस्तेमाल करने से पहले, सही आर्टफ़ैक्ट इस तरह जोड़ें:
Flow:collectAsStateWithLifecycle()collectAsStateWithLifecycle(), लाइफ़साइकल के बारे में जानकारी रखने वालेFlowसे वैल्यू इकट्ठा करता है. इससे आपका ऐप्लिकेशन, ऐप्लिकेशन के संसाधनों को बचा पाता है. यह ComposeStateसे हाल ही में निकाली गई वैल्यू को दिखाता है. Android ऐप्लिकेशन पर फ़्लो इकट्ठा करने के लिए, इस एपीआई का इस्तेमाल करें.build.gradleफ़ाइल में यह डिपेंडेंसी होना ज़रूरी है. यह 2.6.0-beta01 या इससे नया वर्शन होना चाहिए:
Kotlin
dependencies {
...
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.10.0")
}
Groovy
dependencies {
...
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.10.0"
}
-
collectAsState,collectAsStateWithLifecycleसे मिलता-जुलता है. ऐसा इसलिए, क्योंकि यह भीFlowसे वैल्यू इकट्ठा करता है और उन्हें ComposeStateमें बदलता है.सिर्फ़ Android के लिए उपलब्ध
collectAsStateWithLifecycleके बजाय, प्लैटफ़ॉर्म से अलग कोड के लिएcollectAsStateका इस्तेमाल करें.collectAsStateके लिए, किसी अन्य डिपेंडेंसी की ज़रूरत नहीं होती, क्योंकि यहcompose-runtimeमें उपलब्ध है. -
observeAsState()इसLiveDataको मॉनिटर करना शुरू करता है औरStateका इस्तेमाल करके इसकी वैल्यू दिखाता है.build.gradleफ़ाइल में, यह डिपेंडेंसी ज़रूरी है:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-livedata:1.12.0")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-livedata:1.12.0"
}
-
subscribeAsState()एक्सटेंशन फ़ंक्शन हैं. ये RxJava2 के रिएक्टिव स्ट्रीम (जैसे किSingle,Observable,Completable) को ComposeStateमें बदलते हैं.build.gradleफ़ाइल में, यह डिपेंडेंसी ज़रूरी है:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-rxjava2:1.12.0")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-rxjava2:1.12.0"
}
-
subscribeAsState()एक्सटेंशन फ़ंक्शन हैं. ये RxJava3 के रिएक्टिव स्ट्रीम (जैसे किSingle,Observable,Completable) को ComposeStateमें बदलते हैं.build.gradleफ़ाइल में, यह डिपेंडेंसी ज़रूरी है:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-rxjava3:1.12.0")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-rxjava3:1.12.0"
}
स्टेटफ़ुल बनाम स्टेटलेस
remember का इस्तेमाल करके किसी ऑब्जेक्ट को सेव करने वाला कंपोज़ेबल, इंटरनल स्टेट बनाता है. इससे कंपोज़ेबल स्टेटफ़ुल हो जाता है. HelloContent, स्टेटफ़ुल कंपोज़ेबल का एक उदाहरण है. ऐसा इसलिए, क्योंकि यह अपनी name स्थिति को अंदरूनी तौर पर बनाए रखता है और उसमें बदलाव करता है. यह उन स्थितियों में काम आ सकता है जहां कॉल करने वाले को स्थिति को कंट्रोल करने की ज़रूरत नहीं होती है और वह स्थिति को खुद मैनेज किए बिना इसका इस्तेमाल कर सकता है. हालांकि, इंटरनल स्टेट वाले कंपोज़ेबल को कम बार इस्तेमाल किया जा सकता है और उन्हें टेस्ट करना मुश्किल होता है.
स्टेटलेस कंपोज़ेबल, ऐसा कंपोज़ेबल होता है जिसमें कोई भी स्टेट नहीं होती. स्टेटलेसनेस हासिल करने का एक सामान्य तरीका, स्टेट होइस्टिंग का इस्तेमाल करना है.
बार-बार इस्तेमाल किए जा सकने वाले कंपोज़ेबल बनाते समय, अक्सर आपको एक ही कंपोज़ेबल के स्टेटफ़ुल और स्टेटलेस, दोनों वर्शन दिखाने होते हैं. स्टेटफ़ुल वर्शन उन लोगों के लिए सुविधाजनक है जिन्हें स्थिति के बारे में जानकारी नहीं चाहिए. वहीं, स्टेटलेस वर्शन उन लोगों के लिए ज़रूरी है जिन्हें स्थिति को कंट्रोल या बढ़ाना है.
स्टेट होइस्टिंग
Compose में स्टेट होइस्टिंग एक ऐसा पैटर्न है जिसमें स्टेट को कंपोज़ेबल के कॉलर में ले जाया जाता है, ताकि कंपोज़ेबल को स्टेटलेस बनाया जा सके. Jetpack Compose में स्टेट को ऊपर ले जाने का सामान्य पैटर्न यह है कि स्टेट वैरिएबल को दो पैरामीटर से बदल दिया जाए:
value: T: दिखाने के लिए मौजूदा वैल्यूonValueChange: (T) -> Unit: ऐसा इवेंट जिसमें वैल्यू बदलने का अनुरोध किया गया हो, जहांTसुझाई गई नई वैल्यू है
हालांकि, onValueChange के अलावा, और भी कई तरह के फ़ॉर्मैट इस्तेमाल किए जा सकते हैं. अगर कंपोज़ेबल के लिए ज़्यादा सटीक इवेंट सही हैं, तो आपको उन्हें लैम्डा का इस्तेमाल करके तय करना चाहिए.
इस तरह से होस्ट किए गए स्टेट की कुछ अहम प्रॉपर्टी होती हैं:
- एकमात्र भरोसेमंद सोर्स: डुप्लीकेट करने के बजाय स्टेट को ट्रांसफ़र करके, हम यह पक्का करते हैं कि सिर्फ़ एक भरोसेमंद सोर्स हो. इससे बग से बचने में मदद मिलती है.
- इनकैप्सुलेटेड: सिर्फ़ स्टेटफ़ुल कंपोज़ेबल, अपनी स्थिति में बदलाव कर सकते हैं. यह पूरी तरह से इंटरनल है.
- शेयर की जा सकने वाली: Hoisted state को कई कंपोज़ेबल के साथ शेयर किया जा सकता है. अगर आपको
nameको किसी दूसरे कंपोज़ेबल में पढ़ना है, तो होस्टिंग की मदद से ऐसा किया जा सकता है. - इंटरसेप्ट किया जा सकता है: स्टेटलेस कंपोज़ेबल को कॉल करने वाले लोग, स्टेट बदलने से पहले इवेंट को अनदेखा करने या उनमें बदलाव करने का फ़ैसला कर सकते हैं.
- डिकपल्ड: स्टेटलेस कंपोज़ेबल के लिए स्टेट को किसी भी जगह पर सेव किया जा सकता है. उदाहरण के लिए, अब
nameकोViewModelमें ले जाया जा सकता है.
उदाहरण के तौर पर दिए गए मामले में, HelloContent से name और onValueChange को निकाला जाता है. इसके बाद, उन्हें ट्री में ऊपर की ओर ले जाकर, HelloScreen कंपोज़ेबल में रखा जाता है. यह कंपोज़ेबल, HelloContent को कॉल करता है.
@Composable fun HelloScreen() { var name by rememberSaveable { mutableStateOf("") } HelloContent(name = name, onNameChange = { name = it }) } @Composable fun HelloContent(name: String, onNameChange: (String) -> Unit) { Column(modifier = Modifier.padding(16.dp)) { Text( text = "Hello, $name", modifier = Modifier.padding(bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) OutlinedTextField(value = name, onValueChange = onNameChange, label = { Text("Name") }) } }
स्टेट को HelloContent से बाहर ले जाने पर, कंपोज़ेबल के बारे में तर्क करना, उसे अलग-अलग स्थितियों में फिर से इस्तेमाल करना, और उसे टेस्ट करना आसान हो जाता है. HelloContent को इस बात से अलग कर दिया जाता है कि उसके स्टेटस को कैसे सेव किया जाता है. डिकपल करने का मतलब है कि अगर आपको HelloScreen में बदलाव करना है या इसे बदलना है, तो आपको HelloContent को लागू करने के तरीके में बदलाव करने की ज़रूरत नहीं है.
जिस पैटर्न में स्टेट कम होती है और इवेंट बढ़ते हैं उसे एकतरफ़ा डेटा फ़्लो कहा जाता है. इस मामले में, स्थिति HelloScreen से घटकर HelloContent हो जाती है और इवेंट HelloContent से बढ़कर HelloScreen हो जाते हैं. एकतरफ़ा डेटा फ़्लो का इस्तेमाल करके, यूज़र इंटरफ़ेस (यूआई) में स्टेट दिखाने वाले कंपोज़ेबल को, ऐप्लिकेशन के उन हिस्सों से अलग किया जा सकता है जो स्टेट को सेव और बदलते हैं.
- स्टेट को कम से कम उन सभी कंपोज़ेबल के सबसे सामान्य पैरंट तक ले जाना चाहिए जो स्टेट का इस्तेमाल करते हैं (पढ़ते हैं).
- स्टेट को कम से कम उस सबसे ऊंचे लेवल पर ले जाना चाहिए जहां इसे बदला जा सकता है (लिखा जा सकता है).
- अगर एक ही इवेंट के जवाब में दो स्थितियां बदलती हैं, तो उन्हें एक साथ ऊपर ले जाना चाहिए.
इन नियमों के हिसाब से, राज्य को इससे ज़्यादा लेवल पर ले जाया जा सकता है. हालांकि, राज्य को इससे कम लेवल पर ले जाने से, एकतरफ़ा डेटा फ़्लो को फ़ॉलो करना मुश्किल हो जाता है या ऐसा करना मुमकिन नहीं होता.
ज़्यादा जानने के लिए, स्टेट को कहां होस्ट करें पेज देखें.
Compose में स्टेट को वापस लाना
rememberSaveable API, remember की तरह काम करता है. ऐसा इसलिए, क्योंकि यह रीकंपोज़िशन के दौरान स्थिति को बनाए रखता है. साथ ही, सेव किए गए इंस्टेंस की स्थिति के मैकेनिज़्म का इस्तेमाल करके, गतिविधि या प्रोसेस को फिर से बनाने के दौरान भी स्थिति को बनाए रखता है. उदाहरण के लिए, ऐसा तब होता है, जब स्क्रीन को घुमाया जाता है.
स्टेट को सेव करने के तरीके
Bundle में जोड़े गए सभी डेटा टाइप अपने-आप सेव हो जाते हैं. अगर आपको कोई ऐसी चीज़ सेव करनी है जिसे Bundle में नहीं जोड़ा जा सकता, तो आपके पास कई विकल्प हैं.
पार्सलाइज़
सबसे आसान तरीका यह है कि ऑब्जेक्ट में @Parcelize एनोटेशन जोड़ें. ऑब्जेक्ट को पार्सल किया जा सकता है और इसे बंडल किया जा सकता है. उदाहरण के लिए, यह कोड पार्सल किए जा सकने वाले City डेटा टाइप को बनाता है और उसे स्टेट में सेव करता है.
@Parcelize data class City(val name: String, val country: String) : Parcelable @Composable fun CityScreen() { var selectedCity = rememberSaveable { mutableStateOf(City("Madrid", "Spain")) } }
MapSaver
अगर किसी वजह से @Parcelize सही नहीं है, तो mapSaver का इस्तेमाल करके, किसी ऑब्जेक्ट को वैल्यू के ऐसे सेट में बदलने के लिए अपना नियम तय किया जा सकता है जिसे सिस्टम Bundle में सेव कर सके.
data class City(val name: String, val country: String) val CitySaver = run { val nameKey = "Name" val countryKey = "Country" mapSaver( save = { mapOf(nameKey to it.name, countryKey to it.country) }, restore = { City(it[nameKey] as String, it[countryKey] as String) } ) } @Composable fun CityScreen() { var selectedCity = rememberSaveable(stateSaver = CitySaver) { mutableStateOf(City("Madrid", "Spain")) } }
ListSaver
मैप के लिए कुंजियां तय करने की ज़रूरत से बचने के लिए, listSaver का इस्तेमाल किया जा सकता है. साथ ही, इसके इंडेक्स को कुंजियों के तौर पर इस्तेमाल किया जा सकता है:
data class City(val name: String, val country: String) val CitySaver = listSaver<City, Any>( save = { listOf(it.name, it.country) }, restore = { City(it[0] as String, it[1] as String) } ) @Composable fun CityScreen() { var selectedCity = rememberSaveable(stateSaver = CitySaver) { mutableStateOf(City("Madrid", "Spain")) } }
Compose में स्टेट होल्डर
स्टेट को ऊपर ले जाने की आसान प्रोसेस को कंपोज़ेबल फ़ंक्शन में ही मैनेज किया जा सकता है. हालांकि, अगर ट्रैक किए जाने वाले स्टेट की संख्या बढ़ जाती है या कंपोज़ेबल फ़ंक्शन में लॉजिक लागू करने की ज़रूरत पड़ती है, तो लॉजिक और स्टेट की ज़िम्मेदारियों को अन्य क्लास: स्टेट होल्डर को सौंपना एक अच्छा तरीका है.
ध्यान दें कि अन्य मटीरियल में, स्टेट होल्डर को होइस्ट किए गए स्टेट ऑब्जेक्ट भी कहा जाता है.
ज़्यादा जानने के लिए, Compose में स्टेट होइस्टिंग से जुड़ा दस्तावेज़ देखें. इसके अलावा, आर्किटेक्चर गाइड में स्टेट होल्डर और यूज़र इंटरफ़ेस (यूआई) स्टेट पेज पर भी ज़्यादा जानकारी दी गई है.
कुंजियों में बदलाव होने पर, याद रखने से जुड़ी कैलकुलेशन को फिर से ट्रिगर करें
remember एपीआई का इस्तेमाल अक्सर MutableState के साथ किया जाता है:
var name by remember { mutableStateOf("") }
यहां, remember फ़ंक्शन का इस्तेमाल करने से, MutableState वैल्यू को फिर से कंपोज़ किया जा सकता है.
आम तौर पर, remember में calculation लैम्डा पैरामीटर होता है. जब remember
को पहली बार चलाया जाता है, तो यह calculation लैम्डा को शुरू करता है और उसके नतीजे को सेव करता है. रीकंपोज़िशन के दौरान, remember पिछली बार सेव की गई वैल्यू दिखाता है.
स्टेट को कैश मेमोरी में सेव करने के अलावा, remember का इस्तेमाल करके किसी भी ऑब्जेक्ट या ऑपरेशन के नतीजे को कंपोज़िशन में सेव किया जा सकता है. ऐसा तब किया जाता है, जब ऑब्जेक्ट को शुरू करने या नतीजे का हिसाब लगाने में ज़्यादा समय लगता है. ऐसा हो सकता है कि आपको हर बार इस कैलकुलेशन को दोहराना न पड़े.
उदाहरण के लिए, इस ShaderBrush ऑब्जेक्ट को बनाना, एक महंगा ऑपरेशन है:
val brush = remember { ShaderBrush( BitmapShader( ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT ) ) }
remember, वैल्यू को तब तक सेव करता है, जब तक वह कंपोज़िशन से बाहर नहीं निकल जाती. हालांकि, कैश मेमोरी में सेव की गई वैल्यू को अमान्य करने का एक तरीका है. remember एपीआई, key या keys पैरामीटर भी लेता है. अगर इनमें से कोई भी कुंजी बदलती है, तो अगली बार जब फ़ंक्शन remember रीकंपोज़ होता है, तो वह कैश मेमोरी को अमान्य कर देता है और कैलकुलेशन लैम्ब्डा ब्लॉक को फिर से लागू करता है. इस तरीके से, आपको कंपोज़िशन में किसी ऑब्जेक्ट के लाइफ़टाइम को कंट्रोल करने का विकल्प मिलता है. यह कैलकुलेशन तब तक मान्य रहती है, जब तक इनपुट में बदलाव नहीं होता. यह तब तक मान्य नहीं रहती, जब तक याद रखी गई वैल्यू कंपोज़िशन से हट नहीं जाती.
यहां दिए गए उदाहरणों में बताया गया है कि यह तरीका कैसे काम करता है.
इस स्निपेट में, एक ShaderBrush बनाया गया है और इसका इस्तेमाल Box कंपोज़ेबल के बैकग्राउंड पेंट के तौर पर किया गया है. remember, ShaderBrush इंस्टेंस को सेव करता है. ऐसा इसलिए, क्योंकि इसे फिर से बनाना महंगा होता है. इसके बारे में पहले बताया जा चुका है. remember, key1 पैरामीटर के तौर पर avatarRes लेता है. यह चुनी गई बैकग्राउंड इमेज होती है. अगर avatarRes बदलता है, तो ब्रश नई इमेज के साथ फिर से कंपोज़ होता है और Box पर फिर से लागू होता है. ऐसा तब हो सकता है, जब उपयोगकर्ता पिकर से कोई दूसरी इमेज चुनकर उसे बैकग्राउंड के तौर पर सेट करे.
@Composable private fun BackgroundBanner( @DrawableRes avatarRes: Int, modifier: Modifier = Modifier, res: Resources = LocalContext.current.resources ) { val brush = remember(key1 = avatarRes) { ShaderBrush( BitmapShader( ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT ) ) } Box( modifier = modifier.background(brush) ) { /* ... */ } }
अगले स्निपेट में, स्टेट को प्लेन स्टेट होल्डर क्लास
MyAppState में ले जाया गया है. यह remember का इस्तेमाल करके, क्लास के इंस्टेंस को शुरू करने के लिए rememberMyAppState फ़ंक्शन को दिखाता है. Compose में, रीकंपोज़िशन के बाद भी बने रहने वाला इंस्टेंस बनाने के लिए, ऐसे फ़ंक्शन को दिखाने का तरीका आम है. rememberMyAppState फ़ंक्शन को windowSizeClass मिलता है, जो remember के लिए key पैरामीटर के तौर पर काम करता है. अगर इस पैरामीटर में बदलाव होता है, तो ऐप्लिकेशन को नई वैल्यू के साथ, सादे स्टेट होल्डर क्लास को फिर से बनाना होगा. ऐसा तब हो सकता है, जब उपयोगकर्ता डिवाइस को घुमाए.
@Composable private fun rememberMyAppState( windowSizeClass: WindowSizeClass ): MyAppState { return remember(windowSizeClass) { MyAppState(windowSizeClass) } } @Stable class MyAppState( private val windowSizeClass: WindowSizeClass ) { /* ... */ }
Compose, क्लास के equals फ़ंक्शन का इस्तेमाल करके यह तय करता है कि कोई कुंजी बदली है या नहीं. अगर कुंजी बदल गई है, तो वह सेव की गई वैल्यू को अमान्य कर देता है.
रीकंपोज़िशन के बाद भी कुंजियों के साथ स्थिति को सेव करना
rememberSaveable एपीआई, remember के चारों ओर एक रैपर होता है. यह Bundle में डेटा सेव कर सकता है. इस एपीआई की मदद से, स्टेट को न सिर्फ़ रीकंपोज़िशन के बाद भी बचाए रखा जा सकता है, बल्कि ऐक्टिविटी को फिर से बनाया जा सकता है और सिस्टम की ओर से शुरू की गई प्रोसेस को बंद किया जा सकता है.
rememberSaveable को उसी मकसद के लिए input पैरामीटर मिलते हैं जिसके लिए remember को keys पैरामीटर मिलते हैं. इनपुट में बदलाव होने पर, कैश मेमोरी अमान्य हो जाती है. अगली बार जब फ़ंक्शन फिर से कंपोज़ होता है, तो rememberSaveable कैलकुलेशन लैम्डा ब्लॉक को फिर से लागू करता है.
यहां दिए गए उदाहरण में, rememberSaveable userTypedQuery को तब तक सेव करता है, जब तक कि typedQuery में बदलाव नहीं हो जाता:
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
ज़्यादा जानें
स्टेट और Jetpack Compose के बारे में ज़्यादा जानने के लिए, यहां दिए गए अतिरिक्त संसाधन देखें.
सैंपल
कोडलैब
वीडियो
ब्लॉग
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक का टेक्स्ट दिखता है
- Compose यूज़र इंटरफ़ेस (यूआई) का आर्किटेक्चर तैयार करना
- Compose में यूज़र इंटरफ़ेस (यूआई) की स्थिति सेव करना
- Compose में साइड इफ़ेक्ट