स्थिति और Jetpack Compose

ऐप्लिकेशन में मौजूद कोई भी वैल्यू, स्टेटस कहलाती है. यह समय के साथ बदल सकती है. यह एक बहुत ही व्यापक परिभाषा है. इसमें Room डेटाबेस से लेकर किसी क्लास में मौजूद वैरिएबल तक, सभी चीज़ें शामिल हैं.

सभी Android ऐप्लिकेशन, उपयोगकर्ता को स्थिति दिखाते हैं. Android ऐप्लिकेशन में स्टेटस के कुछ उदाहरण:

  • स्नैकबार, जो नेटवर्क कनेक्शन न होने पर दिखता है.
  • ब्लॉग पोस्ट और उससे जुड़ी टिप्पणियां.
  • बटन पर रिपल एनिमेशन, जो उपयोगकर्ता के क्लिक करने पर चलता है.
  • ऐसे स्टिकर जिन्हें उपयोगकर्ता किसी इमेज के ऊपर जोड़ सकता है.

Jetpack Compose की मदद से, यह साफ़ तौर पर बताया जा सकता है कि Android ऐप्लिकेशन में स्टेट को कहां और कैसे सेव किया जाता है और उसका इस्तेमाल कैसे किया जाता है. इस गाइड में, स्टेट और कॉम्पोज़ेबल के बीच के कनेक्शन के साथ-साथ उन एपीआई पर फ़ोकस किया गया है जो Jetpack Compose, स्टेट के साथ आसानी से काम करने के लिए उपलब्ध कराता है.

स्थिति और कंपोज़िशन

Compose एक एनोटेशन है. इसे अपडेट करने का एक ही तरीका है, नए आर्ग्युमेंट के साथ उसी composable को कॉल करना. ये आर्ग्युमेंट, यूज़र इंटरफ़ेस (यूआई) की स्थिति को दिखाते हैं. जब भी कोई स्टेटस अपडेट होता है, तो फिर से कॉम्पोज़ किया जाता है. इस वजह से, 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 में कॉम्पोज़िशन और फिर से कॉम्पोज़ करने की सुविधा अलग-अलग तरीके से काम करती है.

शुरुआती कॉम्पोज़िशन और फिर से कॉम्पोज़ करने के बारे में ज़्यादा जानने के लिए, कॉम्पोज़ करने के बारे में सोचना लेख पढ़ें.

कॉम्पोनेंसेज़ में स्टेटस

कॉम्पोज़ेबल फ़ंक्शन, किसी ऑब्जेक्ट को मेमोरी में सेव करने के लिए, remember एपीआई का इस्तेमाल कर सकते हैं. remember से कैलकुलेट की गई वैल्यू, कॉम्पोज़िशन बनाने के दौरान कॉम्पोज़िशन में सेव की जाती है. साथ ही, कॉम्पोज़िशन फिर से बनाने के दौरान सेव की गई वैल्यू दिखाती है. remember का इस्तेमाल, बदले जा सकने वाले और नहीं बदले जा सकने वाले, दोनों ऑब्जेक्ट को सेव करने के लिए किया जा सकता है.

mutableStateOf एक ऑब्ज़र्वेबल MutableState<T> बनाता है, जो Compose रनटाइम के साथ इंटिग्रेट किया गया ऑब्ज़र्वेबल टाइप है.

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 से वैल्यू इकट्ठा करता है. इससे आपके ऐप्लिकेशन को ऐप्लिकेशन के संसाधनों को बचाने में मदद मिलती है. यह Compose State से उत्सर्जित की गई सबसे नई वैल्यू दिखाता है. Android ऐप्लिकेशन पर फ़्लो इकट्ठा करने के लिए, इस एपीआई का इस्तेमाल करें.

    build.gradle फ़ाइल में यह डिपेंडेंसी ज़रूरी है. यह 2.6.0-beta01 या उससे नया वर्शन होना चाहिए:

Kotlin

dependencies {
      ...
      implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.7")
}

Groovy

dependencies {
      ...
      implementation "androidx.lifecycle:lifecycle-runtime-compose:2.8.7"
}
  • Flow: collectAsState()

    collectAsState, collectAsStateWithLifecycle से मिलता-जुलता है, क्योंकि यह भी Flow से वैल्यू इकट्ठा करता है और उसे Compose State में बदल देता है.

    सिर्फ़ Android के लिए बने collectAsStateWithLifecycle के बजाय, collectAsState का इस्तेमाल करें.

    collectAsState के लिए, अतिरिक्त डिपेंडेंसी की ज़रूरत नहीं है, क्योंकि यह compose-runtime में उपलब्ध है.

  • LiveData: observeAsState()

    observeAsState() इस LiveData को मॉनिटर करना शुरू करता है और State के ज़रिए इसकी वैल्यू दिखाता है.

    build.gradle फ़ाइल में, यह डिपेंडेंसी ज़रूरी है:

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-livedata:1.7.5")
}

Groovy

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-livedata:1.7.5"
}

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-rxjava2:1.7.5")
}

Groovy

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-rxjava2:1.7.5"
}

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-rxjava3:1.7.5")
}

Groovy

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-rxjava3:1.7.5"
}

स्टेटफ़ुल बनाम स्टेटलेस

कोई ऐसा कॉम्पोज़ेबल जो किसी ऑब्जेक्ट को सेव करने के लिए 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 लैम्ब्डा फ़ंक्शन को ट्रिगर करता है और उसका नतीजा सेव करता है. फिर से कॉम्पोज़ करने के दौरान, 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 कैलकुलेशन वाले lambda ब्लॉक को फिर से चलाएगा.

नीचे दिए गए उदाहरण में, rememberSaveable userTypedQuery को तब तक सेव करता है, जब तक कि typedQuery में बदलाव नहीं होता:

var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) {
    mutableStateOf(
        TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length))
    )
}

ज़्यादा जानें

स्टेट और Jetpack Compose के बारे में ज़्यादा जानने के लिए, यहां दिए गए अन्य रिसॉर्स देखें.

सैंपल

कोडलैब

वीडियो

ब्लॉग