ऐप्लिकेशन में स्टेट, ऐसी वैल्यू होती है जो समय के साथ बदल सकती है. यह बहुत ही व्यापक परिभाषा है. इसमें Room डेटाबेस से लेकर क्लास में मौजूद वैरिएबल तक, सब कुछ शामिल है.
सभी Android ऐप्लिकेशन, उपयोगकर्ता को स्टेटस दिखाते हैं. Android ऐप्लिकेशन में स्टेट के कुछ उदाहरण:
- एक स्नैकबार, जो इंटरनेट कनेक्शन न होने पर दिखता है.
- कोई ब्लॉग पोस्ट और उससे जुड़ी टिप्पणियां.
- बटन पर रिपल ऐनिमेशन, जो उपयोगकर्ता के क्लिक करने पर चलते हैं.
- ऐसे स्टिकर जिन्हें उपयोगकर्ता किसी इमेज के ऊपर ड्रॉ कर सकता है.
Jetpack Compose की मदद से, यह साफ़ तौर पर बताया जा सकता है कि Android ऐप्लिकेशन में स्टेट को कहां और कैसे सेव और इस्तेमाल किया जाए. इस गाइड में, स्टेट और कंपोज़ेबल के बीच के कनेक्शन के बारे में बताया गया है. साथ ही, उन एपीआई के बारे में बताया गया है जो Jetpack Compose, स्टेट के साथ काम करने के लिए उपलब्ध कराता है.
स्टेट और कंपोज़िशन
Compose, डिक्लेरेटिव है. इसलिए, इसे अपडेट करने का एकमात्र तरीका यह है कि नए आर्ग्युमेंट के साथ उसी कंपोज़ेबल को कॉल किया जाए. ये आर्ग्युमेंट, यूज़र इंटरफ़ेस (यूआई) की स्थिति को दिखाते हैं. जब भी कोई स्टेट अपडेट होती है, तब रीकंपोज़िशन होता है. इस वजह से, 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, MutableState<T> को बनाता है. यह एक ऑब्ज़र्वेबल टाइप है, जो Compose रनटाइम के साथ इंटिग्रेट होता है.
interface MutableState<T> : State<T> {
override var value: T
}
value में कोई भी बदलाव होने पर, value को पढ़ने वाले सभी composable functions को फिर से कंपोज़ करने के लिए शेड्यूल किया जाता है.
कंपोज़ेबल में 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.11.0")
}
Groovy
dependencies {
...
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.11.0"
}
-
collectAsState,collectAsStateWithLifecycleसे मिलता-जुलता है, क्योंकि यह भीFlowसे वैल्यू इकट्ठा करता है और उसे ComposeStateमें बदलता है.collectAsStateWithLifecycleके बजाय, प्लैटफ़ॉर्म-एग्नोस्टिक कोड के लिएcollectAsStateका इस्तेमाल करें. यह सिर्फ़ Android के लिए है.collectAsStateके लिए, अतिरिक्त डिपेंडेंसी की ज़रूरत नहीं है, क्योंकि यहcompose-runtimeमें उपलब्ध है. -
observeAsState()इसLiveDataको मॉनिटर करना शुरू करता है औरStateका इस्तेमाल करके इसकी वैल्यू दिखाता है.build.gradleफ़ाइल में, यह डिपेंडेंसी ज़रूरी है:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-livedata:1.12.1")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-livedata:1.12.1"
}
-
subscribeAsState(), एक्सटेंशन फ़ंक्शन हैं. ये RxJava2 की रिएक्टिव स्ट्रीम (जैसे,Single,Observable,Completable) को ComposeStateमें बदलते हैं.build.gradleफ़ाइल में, यह डिपेंडेंसी ज़रूरी है:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-rxjava2:1.12.1")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-rxjava2:1.12.1"
}
-
subscribeAsState(), एक्सटेंशन फ़ंक्शन हैं. ये RxJava3 की रिऐक्टिव स्ट्रीम (जैसे,Single,Observable,Completable) को ComposeStateमें बदलते हैं.build.gradleफ़ाइल में, यह डिपेंडेंसी ज़रूरी है:
Kotlin
dependencies {
...
implementation("androidx.compose.runtime:runtime-rxjava3:1.12.1")
}
Groovy
dependencies {
...
implementation "androidx.compose.runtime:runtime-rxjava3:1.12.1"
}
स्टेटफ़ुल बनाम स्टेटलेस
ऑब्जेक्ट को स्टोर करने के लिए remember का इस्तेमाल करने वाला कंपोज़ेबल, इंटरनल स्टेट बनाता है. इससे कंपोज़ेबल स्टेटफ़ुल बन जाता है. HelloContent, स्टेटफ़ुल कंपोज़ेबल का एक उदाहरण है. इसकी वजह यह है कि यह अपने name स्टेटस को इंटरनल तौर पर सेव करता है और उसमें बदलाव करता है. यह उन स्थितियों में काम आ सकता है जहां कॉलर को स्टेट को कंट्रोल करने की ज़रूरत नहीं होती. साथ ही, वह स्टेट को खुद मैनेज किए बिना भी इसका इस्तेमाल कर सकता है. हालांकि, इंटरनल स्टेट वाले कंपोज़ेबल को फिर से इस्तेमाल करना मुश्किल होता है. साथ ही, उनकी जांच करना भी मुश्किल होता है.
स्टेटलेस कंपोज़ेबल, ऐसा कंपोज़ेबल होता है जिसमें कोई स्टेट नहीं होती. स्टेटलेसनेस हासिल करने का एक सामान्य तरीका, स्टेट होइस्टिंग का इस्तेमाल करना है.
फिर से इस्तेमाल किए जा सकने वाले कंपोज़ेबल बनाते समय, अक्सर आपको एक ही कंपोज़ेबल के स्टेटफ़ुल और स्टेटलेस, दोनों वर्शन दिखाने होते हैं. स्टेटफ़ुल वर्शन, उन कॉलर के लिए सुविधाजनक है जिन्हें स्टेट की परवाह नहीं होती. वहीं, स्टेटलेस वर्शन उन कॉलर के लिए ज़रूरी है जिन्हें स्टेट को कंट्रोल या होस्ट करना होता है.
स्टेट होइस्टिंग
Compose में स्टेट होइस्टिंग, स्टेट को कंपोज़ेबल के कॉलर पर ले जाने का एक पैटर्न है, ताकि कंपोज़ेबल को स्टेटलेस बनाया जा सके. Jetpack Compose में स्टेट होइस्टिंग का सामान्य पैटर्न, स्टेट वैरिएबल को दो पैरामीटर से बदलना है:
value: T: दिखाई जाने वाली मौजूदा वैल्यूonValueChange: (T) -> Unit: यह एक ऐसा इवेंट है जो वैल्यू बदलने का अनुरोध करता है. इसमेंT, सुझाई गई नई वैल्यू है
हालांकि, आपके पास onValueChange के अलावा अन्य विकल्प भी हैं. अगर कंपोज़ेबल के लिए ज़्यादा सटीक इवेंट सही हैं, तो आपको उन्हें लैम्ब्डा का इस्तेमाल करके तय करना चाहिए.
इस तरह से होस्ट किए गए स्टेट में कुछ अहम प्रॉपर्टी होती हैं:
- एकमात्र भरोसेमंद सोर्स: स्टेट को डुप्लीकेट करने के बजाय उसे मूव करने से, हम यह पक्का कर रहे हैं कि सिर्फ़ एक भरोसेमंद सोर्स हो. इससे बग से बचने में मदद मिलती है.
- एनकैप्सुलेटेड: सिर्फ़ स्टेटफ़ुल कंपोज़ेबल ही अपनी स्थिति में बदलाव कर सकते हैं. यह पूरी तरह से इंटरनल है.
- शेयर किया जा सकता है: होस्ट किए गए स्टेट को कई कंपोज़ेबल के साथ शेयर किया जा सकता है. अगर आपको
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 एपीआई, remember की तरह ही काम करता है. ऐसा इसलिए, क्योंकि यह रीकंपोज़िशन के साथ-साथ, सेव किए गए इंस्टेंस स्टेट मैकेनिज़्म का इस्तेमाल करके, गतिविधि या प्रोसेस को फिर से बनाने के दौरान भी स्टेट को बनाए रखता है. उदाहरण के लिए, ऐसा तब होता है,
जब स्क्रीन को घुमाया जाता है.
स्टेट को सेव करने के तरीके
Bundle में जोड़ा गया हर तरह का डेटा अपने-आप सेव हो जाता है. अगर आपको कोई ऐसा आइटम सेव करना है जिसे Bundle में नहीं जोड़ा जा सकता, तो आपके पास कई विकल्प हैं.
Parcelize
सबसे आसान तरीका यह है कि ऑब्जेक्ट में @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 lambda को शुरू करता है और इसके नतीजे को सेव करता है. रीकंपोज़िशन के दौरान, 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, avatarRes को key1 पैरामीटर के तौर पर लेता है. यह चुनी गई बैकग्राउंड इमेज है. अगर 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 में साइड-इफ़ेक्ट