Compose में यूज़र इंटरफ़ेस (यूआई) की स्थिति सेव करें

अपने राज्य को कहां तक पहुंचाना है और किस लॉजिक की ज़रूरत है, इसके आधार पर आपको आपके यूज़र इंटरफ़ेस (यूआई) की स्थिति को सेव और पहले जैसा करने के लिए, अलग-अलग एपीआई का इस्तेमाल कर सकता है. हर ऐप्लिकेशन, को जोड़ने की कोशिश की.

किसी गतिविधि या प्रोसेस की वजह से, कोई भी Android ऐप्लिकेशन अपनी यूज़र इंटरफ़ेस (यूआई) स्थिति खो सकता है मनोरंजन. स्थिति खो जाने की यह स्थिति इन इवेंट की वजह से हो सकती है:

पॉज़िटिव उपयोगकर्ता के लिए, इन इवेंट के बाद राज्य को सुरक्षित रखना ज़रूरी है अनुभव. यह चुनना कि किस स्थिति को बनाए रखना है, यह आपके ऐप्लिकेशन के यूनीक उपयोगकर्ता पर निर्भर करता है फ़्लो. सबसे सही तरीका यह है कि आपको कम से कम उपयोगकर्ता का इनपुट बनाए रखना चाहिए और नेविगेशन से जुड़ी स्थिति. इसके उदाहरणों में स्क्रोल की स्थिति शामिल है सूची, उस आइटम का आईडी जिसके बारे में उपयोगकर्ता को ज़्यादा जानकारी चाहिए, उपयोगकर्ता की प्राथमिकताओं या टेक्स्ट फ़ील्ड में इनपुट चुनने के लिए किया जा सकता है.

इस पेज पर, यूज़र इंटरफ़ेस (यूआई) की स्थिति को सेव करने के लिए उपलब्ध एपीआई की खास जानकारी दी गई है. यह जानकारी, इस बात पर निर्भर करती है कि अपने राज्य को असाइन किया जाता है.

यूज़र इंटरफ़ेस (यूआई) लॉजिक

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

नीचे दिए गए स्निपेट में, rememberSaveable का इस्तेमाल एक बूलियन को स्टोर करने के लिए किया जाता है यूज़र इंटरफ़ेस (यूआई) एलिमेंट की स्थिति:

@Composable
fun ChatBubble(
    message: Message
) {
    var showDetails by rememberSaveable { mutableStateOf(false) }

    ClickableText(
        text = AnnotatedString(message.content),
        onClick = { showDetails = !showDetails }
    )

    if (showDetails) {
        Text(message.timestamp)
    }
}

पहली इमेज. चैट मैसेज बबल, टैप करने पर बड़ा और छोटा हो जाता है.

showDetails एक बूलियन वैरिएबल है. यह चैट बबल को छोटा करने पर सेव होता है या बड़ा किया गया.

rememberSaveable यूज़र इंटरफ़ेस (यूआई) एलिमेंट की स्थिति को Bundle में इसके ज़रिए सेव करता है: सेव किए गए इंस्टेंस की स्थिति दिखाने का तरीका.

यह बंडल में प्रिमिटिव टाइप को अपने-आप सेव कर सकता है. अगर आपके राज्य का एक ऐसे प्रकार में धारण किया गया हो जो प्रिमिटिव नहीं है, जैसे डेटा क्लास, तो आप डेटा सेव करने के अलग-अलग तरीके, जैसे कि Parcelize एनोटेशन का इस्तेमाल करना, listSaver और mapSaver जैसे Compose API का इस्तेमाल करके या कस्टम सेवर क्लास, कंपोज़ रनटाइम Saver क्लास को बढ़ा रही है. तरीके देखें दस्तावेज़ को सेव करने के लिए कहें. इससे आपको इन तरीकों के बारे में ज़्यादा जानकारी मिलेगी.

नीचे दिए गए स्निपेट में, rememberLazyListState लिखें एपीआई स्टोर LazyListState, जिसमें स्क्रोल की गई rememberSaveable का इस्तेमाल करके, LazyColumn या LazyRow. यह LazyListState.Saver, यह एक कस्टम सेवर है, जो सेव करें और स्क्रोल करने की स्थिति को पहले जैसा करें. किसी गतिविधि या मनोरंजन की प्रक्रिया के बाद (इसके लिए उदाहरण के लिए, डिवाइस की स्क्रीन की दिशा बदलने जैसे कॉन्फ़िगरेशन में बदलाव होने पर, स्क्रोल की स्थिति को सुरक्षित रखा जाता है.

@Composable
fun rememberLazyListState(
    initialFirstVisibleItemIndex: Int = 0,
    initialFirstVisibleItemScrollOffset: Int = 0
): LazyListState {
    return rememberSaveable(saver = LazyListState.Saver) {
        LazyListState(
            initialFirstVisibleItemIndex, initialFirstVisibleItemScrollOffset
        )
    }
}

सबसे सही तरीका

rememberSaveable, यूज़र इंटरफ़ेस (यूआई) स्थिति को सेव करने के लिए Bundle का इस्तेमाल करता है, जिसे इसकी मदद से शेयर किया जाता है अन्य API जो उस पर लिखते हैं, जैसे onSaveInstanceState() कॉल आपकी गतिविधि. हालांकि, इस Bundle का साइज़ सीमित है और यह बड़ी वैल्यू सेव की जा रही है ऑब्जेक्ट, रनटाइम में TransactionTooLarge अपवाद हो सकते हैं. यह खास तौर पर, Activity वाले किसी एक ऐप्लिकेशन में समस्या पैदा कर सकता है. Bundle को पूरे ऐप्लिकेशन में इस्तेमाल किया जा रहा है.

इस तरह के क्रैश से बचने के लिए, आपको बड़े कॉम्प्लेक्स ऑब्जेक्ट या बंडल में मौजूद ऑब्जेक्ट की सूचियां.

इसके बजाय, आईडी या कुंजियों जैसी कम से कम ज़रूरी स्थिति को सेव करें. साथ ही, इनका इस्तेमाल इन कामों के लिए करें ज़्यादा कॉम्प्लेक्स यूज़र इंटरफ़ेस (यूआई) स्थिति को दूसरे तरीकों, जैसे कि परसिस्टेंट डिराइवेंट डिवाइस की मेमोरी पर टैप करें.

डिज़ाइन के ये विकल्प, इस बात पर निर्भर करते हैं कि आपका ऐप्लिकेशन किस तरह से इस्तेमाल किया जाता है. साथ ही, उपयोगकर्ता उम्मीद करते हैं कि यह ठीक से काम करेगा.

राज्य से वापस लाने की पुष्टि करें

यह पुष्टि की जा सकती है कि rememberSaveable के साथ सेव किया गया राज्य गतिविधि या प्रोसेस के फिर से बनाया गया. इसे पाने के लिए कुछ खास एपीआई हैं. जैसे, StateRestorationTester. जांच करने से जुड़ा दस्तावेज़ देखें ज़्यादा जानें.

बिज़नेस लॉजिक

अगर आपके यूज़र इंटरफ़ेस (यूआई) एलिमेंट की स्थिति को ViewModel पर ले जाया जाता है, क्योंकि यह कारोबारी लॉजिक के मुताबिक ज़रूरी है, तो आपके पास ViewModel के एपीआई का इस्तेमाल करने का विकल्प है.

अपने Android ऐप्लिकेशन में ViewModel इस्तेमाल करने का एक मुख्य फ़ायदा यह है यह कॉन्फ़िगरेशन के बदलावों को मुफ़्त में हैंडल करता है. कॉन्फ़िगरेशन होने पर बदलाव हो जाता है और गतिविधि को नष्ट कर दिया जाता है और फिर से बनाया जाता है, तो यूज़र इंटरफ़ेस (यूआई) की स्थिति ViewModel को मेमोरी में रखा गया है. मनोरंजन के बाद, पुराना ViewModel इंस्टेंस को नए ऐक्टिविटी इंस्टेंस से अटैच किया गया है.

हालांकि, ViewModel इंस्टेंस, सिस्टम से शुरू की गई प्रोसेस के खत्म होने से नहीं बचा जा सकता. यूज़र इंटरफ़ेस (यूआई) की स्थिति को बनाए रखने के लिए, 'सेव की गई स्थिति' मॉड्यूल का इस्तेमाल करें ViewModel, जिसमें SavedStateHandle एपीआई शामिल है.

सबसे सही तरीका

SavedStateHandle यूज़र इंटरफ़ेस (यूआई) की स्थिति को सेव करने के लिए, Bundle तरीके का इस्तेमाल करता है. इसलिए, आपको इसका इस्तेमाल सिर्फ़ आसान यूज़र इंटरफ़ेस (यूआई) एलिमेंट की स्थिति को सेव करने के लिए करना चाहिए.

स्क्रीन यूज़र इंटरफ़ेस (यूआई) की स्थिति, जो कारोबार के नियमों को लागू करके और ऐक्सेस करके बनाई जाती है यूज़र इंटरफ़ेस (यूआई) के अलावा आपके ऐप्लिकेशन की अन्य परतें, इसमें संग्रहित नहीं होनी चाहिए SavedStateHandle है, क्योंकि इसके साइज़ में आने वाली दिक्कतें हैं. Google Analytics 4 पर माइग्रेट करने के लिए, कॉम्प्लेक्स या बड़े डेटा को स्टोर करने के अलग-अलग तरीके. जैसे, लोकल परसिस्टेंट डिवाइस की मेमोरी पर टैप करें. प्रोसेस फिर से शुरू करने के बाद, स्क्रीन को कुछ समय के लिए पहले जैसी की गई उसे SavedStateHandle (अगर कोई है) में सेव किया गया था, और स्क्रीन के यूज़र इंटरफ़ेस (यूआई) की स्थिति को डेटा लेयर से फिर से जनरेट किया जाता है.

SavedStateHandle एपीआई

यूज़र इंटरफ़ेस (यूआई) एलिमेंट की स्थिति को सेव करने के लिए, SavedStateHandle में अलग-अलग एपीआई हैं. ज़्यादातर खास तौर पर:

लिखें State saveable()
StateFlow getStateFlow()

State लिखें

यूज़र इंटरफ़ेस (यूआई) एलिमेंट को पढ़ने और उसमें बदलाव करने के लिए, SavedStateHandle के saveable एपीआई का इस्तेमाल करें राज्य MutableState है, इसलिए यह गतिविधि के बने रहते हैं और इनके साथ मनोरंजन का काम करते हैं कम से कम कोड सेटअप.

saveable एपीआई, प्रिमिटिव टाइप के साथ काम करता है. साथ ही, इसे rememberSaveable() की तरह, कस्टम सेवर का इस्तेमाल करने के लिए stateSaver पैरामीटर.

नीचे दिए गए स्निपेट में, message उपयोगकर्ता के इनपुट टाइप को TextField:

class ConversationViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    var message by savedStateHandle.saveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue(""))
    }
        private set

    fun update(newMessage: TextFieldValue) {
        message = newMessage
    }

    /*...*/
}

val viewModel = ConversationViewModel(SavedStateHandle())

@Composable
fun UserInput(/*...*/) {
    TextField(
        value = viewModel.message,
        onValueChange = { viewModel.update(it) }
    )
}

SavedStateHandle के बारे में ज़्यादा जानकारी पाने के लिए, यह दस्तावेज़ पढ़ें saveable एपीआई का इस्तेमाल करके.

StateFlow

यूज़र इंटरफ़ेस (यूआई) एलिमेंट की स्थिति को सेव करने और उसे फ़्लो के रूप में इस्तेमाल करने के लिए, getStateFlow() का इस्तेमाल करें SavedStateHandle से. StateFlow को पढ़ लिया गया है है, और एपीआई का इस्तेमाल करने के लिए आपको एक कुंजी तय करनी होगी, ताकि आप फ़्लो को बदल सकें कोई नई वैल्यू असाइन करें. आपने जो कुंजी कॉन्फ़िगर की है उसकी मदद से, StateFlow को वापस पाया जा सकता है और सबसे नई वैल्यू इकट्ठा करें.

नीचे दिए गए स्निपेट में, savedFilterType एक StateFlow वैरिएबल है इस सेटिंग में, चैट ऐप्लिकेशन में चैट चैनलों की सूची पर लागू फ़िल्टर टाइप को सेव किया जाता है:

private const val CHANNEL_FILTER_SAVED_STATE_KEY = "ChannelFilterKey"

class ChannelViewModel(
    channelsRepository: ChannelsRepository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val savedFilterType: StateFlow<ChannelsFilterType> = savedStateHandle.getStateFlow(
        key = CHANNEL_FILTER_SAVED_STATE_KEY, initialValue = ChannelsFilterType.ALL_CHANNELS
    )

    private val filteredChannels: Flow<List<Channel>> =
        combine(channelsRepository.getAll(), savedFilterType) { channels, type ->
            filter(channels, type)
        }.onStart { emit(emptyList()) }

    fun setFiltering(requestType: ChannelsFilterType) {
        savedStateHandle[CHANNEL_FILTER_SAVED_STATE_KEY] = requestType
    }

    /*...*/
}

enum class ChannelsFilterType {
    ALL_CHANNELS, RECENT_CHANNELS, ARCHIVED_CHANNELS
}

जब भी उपयोगकर्ता कोई नया फ़िल्टर टाइप चुनता है, तो setFiltering को कॉल किया जाता है. यह कुंजी के साथ सेव किए गए SavedStateHandle में नई वैल्यू सेव करता है _CHANNEL_FILTER_SAVED_STATE_KEY_. savedFilterType एक ऐसा फ़्लो है जो कुंजी में सेव किया गया सबसे नया मान. filteredChannels ने फ़्लो की सदस्यता ली है: चैनल को फ़िल्टर करने का विकल्प होता है.

इस बारे में ज़्यादा जानकारी के लिए, SavedStateHandle दस्तावेज़ देखें getStateFlow() एपीआई.

खास जानकारी

यहां दी गई टेबल में, इस सेक्शन में शामिल एपीआई के बारे में खास जानकारी दी गई है. साथ ही, यह भी बताया गया है कि इनका इस्तेमाल कब करना चाहिए हर यूज़र इंटरफ़ेस (यूआई) स्थिति को सेव करने के लिए:

इवेंट यूज़र इंटरफ़ेस (यूआई) लॉजिक ViewModel में बिज़नेस लॉजिक
कॉन्फ़िगरेशन में बदलाव rememberSaveable अपने-आप
सिस्टम की ओर से शुरू की गई प्रोसेस बंद होना rememberSaveable SavedStateHandle

एपीआई का इस्तेमाल किस राज्य में किया जा रहा है और यह किस लॉजिक के आधार पर किया जाना है, यह इस बात पर निर्भर करता है आवश्यक है. यूज़र इंटरफ़ेस (यूआई) लॉजिक में इस्तेमाल होने वाली स्थिति के लिए, rememberSaveable का इस्तेमाल करें. इसके लिए राज्य का इस्तेमाल कारोबार के नियम में किया जाता है. अगर आपने इसे ViewModel में होल्ड किया हुआ है, SavedStateHandle का इस्तेमाल करके उसे सेव करें.

इन कामों के लिए आपको बंडल एपीआई (rememberSaveable और SavedStateHandle) का इस्तेमाल करना चाहिए यूज़र इंटरफ़ेस (यूआई) स्थिति को थोड़ा सा सेव करें. यह डेटा वापस लाने के लिए ज़रूरी कम से कम डेटा है अन्य स्टोर करने के तरीकों के साथ, यूज़र इंटरफ़ेस (यूआई) को उसकी पिछली स्थिति पर वापस ले जाता है. इसके लिए उदाहरण के लिए, अगर आपने उस प्रोफ़ाइल का आईडी सेव किया है जिसे उपयोगकर्ता बंडल में देख रहा था, डेटा लेयर से, प्रोफ़ाइल की जानकारी जैसा भारी डेटा फ़ेच किया जा सकता है.

यूज़र इंटरफ़ेस (यूआई) की स्थिति को सेव करने के अलग-अलग तरीकों के बारे में ज़्यादा जानने के लिए, यूज़र इंटरफ़ेस (यूआई) की स्थिति से जुड़े दस्तावेज़ और इसके डेटा लेयर पेज को सेव करना आर्किटेक्चर गाइड देखें.