साइड-इफ़ेक्ट, ऐप्लिकेशन की स्थिति में ऐसा बदलाव होता है जो किसी कॉम्पोज़ेबल फ़ंक्शन के दायरे से बाहर होता है. कॉम्पोज़ेबल के लाइफ़साइकल और प्रॉपर्टी की वजह से, कॉम्पोज़ेबल आदर्श रूप से साइड-इफ़ेक्ट के बिना होने चाहिए. जैसे, अचानक होने वाले फिर से कॉम्पोज़ होने की प्रोसेस, अलग-अलग क्रम में कॉम्पोज़ेबल फिर से कॉम्पोज़ करने की प्रोसेस या फिर से कॉम्पोज़ करने की ऐसी प्रोसेस जिसे खारिज किया जा सकता है.
हालांकि, कभी-कभी साइड इफ़ेक्ट ज़रूरी होते हैं. उदाहरण के लिए, एक बार होने वाले इवेंट को ट्रिगर करने के लिए, जैसे कि स्नैकबार दिखाना या किसी खास स्थिति के हिसाब से किसी दूसरी स्क्रीन पर नेविगेट करना. इन कार्रवाइयों को ऐसे कंट्रोल किए गए एनवायरमेंट से कॉल किया जाना चाहिए जो कॉम्पोज़ेबल के लाइफ़साइकल के बारे में जानता हो. इस पेज पर, आपको अलग-अलग साइड-इफ़ेक्ट एपीआई के बारे में जानकारी मिलेगी.
स्टेट और इफ़ेक्ट के इस्तेमाल के उदाहरण
Compose के बारे में सोचना दस्तावेज़ में बताया गया है कि कॉम्पोज़ेबल में कोई साइड इफ़ेक्ट नहीं होना चाहिए. जब आपको ऐप्लिकेशन की स्थिति में बदलाव करने हों (जैसा कि स्थिति मैनेज करने के दस्तावेज़ में बताया गया है), तो आपको इफ़ेक्ट एपीआई का इस्तेमाल करना चाहिए, ताकि वे साइड इफ़ेक्ट अनुमानित तरीके से लागू हों.
Compose में अलग-अलग तरह के इफ़ेक्ट इस्तेमाल किए जा सकते हैं. इसलिए, इनका ज़रूरत से ज़्यादा इस्तेमाल किया जा सकता है. पक्का करें कि इनमें किया जाने वाला काम, यूज़र इंटरफ़ेस (यूआई) से जुड़ा हो और स्टेटस मैनेज करने के दस्तावेज़ में बताए गए तरीके से, एकतरफ़ा डेटा फ़्लो में रुकावट न डाले.
LaunchedEffect
: किसी कॉम्पोज़ेबल के दायरे में सस्पेंड फ़ंक्शन चलाना
किसी कॉम्पोज़ेबल के लाइफ़साइकल के दौरान काम करने और सस्पेंड फ़ंक्शन को कॉल करने के लिए, LaunchedEffect
कॉम्पोज़ेबल का इस्तेमाल करें. जब LaunchedEffect
, कॉम्पोज़िशन में शामिल होता है, तो पैरामीटर के तौर पर पास किए गए कोड के ब्लॉक के साथ एक कोरुटिन लॉन्च होता है. अगर LaunchedEffect
कॉम्पोज़िशन छोड़ता है, तो कोरुटाइन रद्द हो जाएगा. अगर LaunchedEffect
को अलग-अलग कुंजियों के साथ फिर से बनाया जाता है (फिर से शुरू करने के असर सेक्शन देखें), तो मौजूदा कोरूटीन रद्द कर दिया जाएगा और नए कोरूटीन में, सस्पेंड करने का नया फ़ंक्शन लॉन्च किया जाएगा.
उदाहरण के लिए, यहां एक ऐसा ऐनिमेशन दिया गया है जिसमें अल्फा वैल्यू को, कॉन्फ़िगर किए जा सकने वाले डिले के साथ पल्से किया गया है:
// Allow the pulse rate to be configured, so it can be sped up if the user is running // out of time var pulseRateMs by remember { mutableStateOf(3000L) } val alpha = remember { Animatable(1f) } LaunchedEffect(pulseRateMs) { // Restart the effect when the pulse rate changes while (isActive) { delay(pulseRateMs) // Pulse the alpha every pulseRateMs to alert the user alpha.animateTo(0f) alpha.animateTo(1f) } }
ऊपर दिए गए कोड में, ऐनिमेशन में तय समय तक इंतज़ार करने के लिए, निलंबित करने वाले फ़ंक्शन delay
का इस्तेमाल किया गया है. इसके बाद, यह animateTo
का इस्तेमाल करके, ऐल्फ़ा को क्रम से शून्य तक और फिर से वापस ले जाता है.
यह प्रोसेस, कॉम्पोज़ेबल के इस्तेमाल के दौरान बार-बार होगी.
rememberCoroutineScope
: किसी कॉम्पोज़ेबल के बाहर कोरुटाइन लॉन्च करने के लिए, कॉम्पोज़िशन के बारे में जानकारी देने वाला स्कोप पाना
LaunchedEffect
एक कंपोजेबल फ़ंक्शन है, इसलिए इसका इस्तेमाल सिर्फ़ दूसरे कंपोजेबल फ़ंक्शन में किया जा सकता है. किसी कॉम्पोज़ेबल के बाहर कोरुटाइन लॉन्च करने के लिए,
rememberCoroutineScope
का इस्तेमाल करें. इससे, कॉम्पोज़िशन से बाहर निकलने पर कोरुटाइन अपने-आप रद्द हो जाएगा.
जब भी आपको एक या उससे ज़्यादा कोरयूटीन के लाइफ़साइकल को मैन्युअल तरीके से कंट्रोल करना हो, तब भी rememberCoroutineScope
का इस्तेमाल करें. उदाहरण के लिए, उपयोगकर्ता इवेंट होने पर ऐनिमेशन को रद्द करना.
rememberCoroutineScope
एक कंपोजेबल फ़ंक्शन है, जो कॉम्पोज़िशन के उस पॉइंट से बंधा CoroutineScope
दिखाता है जहां इसे कॉल किया गया है. कॉल से बाहर निकलने पर, स्कोप रद्द हो जाएगा.
पिछले उदाहरण के आधार पर, इस कोड का इस्तेमाल करके, उपयोगकर्ता के Button
पर टैप करने पर Snackbar
दिखाया जा सकता है:
@Composable fun MoviesScreen(snackbarHostState: SnackbarHostState) { // Creates a CoroutineScope bound to the MoviesScreen's lifecycle val scope = rememberCoroutineScope() Scaffold( snackbarHost = { SnackbarHost(hostState = snackbarHostState) } ) { contentPadding -> Column(Modifier.padding(contentPadding)) { Button( onClick = { // Create a new coroutine in the event handler to show a snackbar scope.launch { snackbarHostState.showSnackbar("Something happened!") } } ) { Text("Press me") } } } }
rememberUpdatedState
: किसी ऐसे इफ़ेक्ट में वैल्यू का रेफ़रंस देना जिसे वैल्यू बदलने पर रीस्टार्ट नहीं करना चाहिए
किसी मुख्य पैरामीटर में बदलाव होने पर, LaunchedEffect
फिर से शुरू हो जाता है. हालांकि, कुछ मामलों में हो सकता है कि आप अपने इफ़ेक्ट में ऐसी वैल्यू कैप्चर करना चाहें जिसे बदलने पर, इफ़ेक्ट फिर से शुरू न हो. ऐसा करने के लिए, rememberUpdatedState
का इस्तेमाल करके इस वैल्यू का रेफ़रंस बनाएं, जिसे कैप्चर और अपडेट किया जा सकता है. यह तरीका उन इफ़ेक्ट के लिए मददगार होता है जिनमें लंबे समय तक चलने वाले ऑपरेशन होते हैं. इन्हें फिर से बनाना और फिर से शुरू करना महंगा या मुश्किल हो सकता है.
उदाहरण के लिए, मान लें कि आपके ऐप्लिकेशन में एक LandingScreen
है जो कुछ समय बाद दिखना बंद हो जाता है. भले ही LandingScreen
को फिर से कॉम्पोज़ किया गया हो, लेकिन कुछ समय तक इंतज़ार करने वाले और यह सूचना देने वाले इफ़ेक्ट को फिर से शुरू नहीं किया जाना चाहिए:
@Composable fun LandingScreen(onTimeout: () -> Unit) { // This will always refer to the latest onTimeout function that // LandingScreen was recomposed with val currentOnTimeout by rememberUpdatedState(onTimeout) // Create an effect that matches the lifecycle of LandingScreen. // If LandingScreen recomposes, the delay shouldn't start again. LaunchedEffect(true) { delay(SplashWaitTimeMillis) currentOnTimeout() } /* Landing screen content */ }
कॉल साइट के लाइफ़साइकल से मैच करने वाला इफ़ेक्ट बनाने के लिए, Unit
या true
जैसे कभी न बदलने वाले कॉन्स्टेंट को पैरामीटर के तौर पर पास किया जाता है. ऊपर दिए गए कोड में, LaunchedEffect(true)
का इस्तेमाल किया गया है. यह पक्का करने के लिए कि onTimeout
लैम्ब्डा में हमेशा वह नई वैल्यू मौजूद हो जिससे LandingScreen
को फिर से कॉम्पोज़ किया गया था, onTimeout
को rememberUpdatedState
फ़ंक्शन के साथ रैप करना होगा.
कोड में दिखाए गए State
, currentOnTimeout
का इस्तेमाल इफ़ेक्ट में किया जाना चाहिए.
DisposableEffect
: ऐसे इफ़ेक्ट जिन्हें क्लीनअप करना ज़रूरी है
बटन बदलने के बाद, जिन साइड इफ़ेक्ट को साफ़ करना ज़रूरी है या अगर कॉम्पोज़ेबल, कॉम्पोज़िशन से बाहर निकल जाता है, तो DisposableEffect
का इस्तेमाल करें.
अगर DisposableEffect
बटन बदलते हैं, तो कॉम्पोज़ेबल को अपने मौजूदा इफ़ेक्ट को खारिज (साफ़ करना) करना होगा. इसके बाद, इफ़ेक्ट को फिर से कॉल करके रीसेट करना होगा.
उदाहरण के लिए, हो सकता है कि आप LifecycleObserver
का इस्तेमाल करके, Lifecycle
इवेंट के आधार पर Analytics इवेंट भेजना चाहें.
Compose में उन इवेंट को सुनने के लिए, DisposableEffect
का इस्तेमाल करके, ज़रूरत पड़ने पर ऑब्ज़र्वर को रजिस्टर और अनरजिस्टर करें.
@Composable fun HomeScreen( lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current, onStart: () -> Unit, // Send the 'started' analytics event onStop: () -> Unit // Send the 'stopped' analytics event ) { // Safely update the current lambdas when a new one is provided val currentOnStart by rememberUpdatedState(onStart) val currentOnStop by rememberUpdatedState(onStop) // If `lifecycleOwner` changes, dispose and reset the effect DisposableEffect(lifecycleOwner) { // Create an observer that triggers our remembered callbacks // for sending analytics events val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_START) { currentOnStart() } else if (event == Lifecycle.Event.ON_STOP) { currentOnStop() } } // Add the observer to the lifecycle lifecycleOwner.lifecycle.addObserver(observer) // When the effect leaves the Composition, remove the observer onDispose { lifecycleOwner.lifecycle.removeObserver(observer) } } /* Home screen content */ }
ऊपर दिए गए कोड में, इफ़ेक्ट lifecycleOwner
में observer
जोड़ देगा. अगर lifecycleOwner
बदलता है, तो इफ़ेक्ट हटा दिया जाता है और नए lifecycleOwner
के साथ फिर से शुरू किया जाता है.
DisposableEffect
कोड के ब्लॉक में, आखिरी स्टेटमेंट के तौर पर onDispose
क्लॉज़ शामिल करना चाहिए. ऐसा न करने पर, IDE में बिल्ड के समय गड़बड़ी का मैसेज दिखता है.
SideEffect
: Compose स्टेटस को Compose के अलावा किसी दूसरे कोड में पब्लिश करना
Compose की स्थिति को उन ऑब्जेक्ट के साथ शेयर करने के लिए जिन्हें Compose से मैनेज नहीं किया जाता, SideEffect
composable का इस्तेमाल करें. SideEffect
का इस्तेमाल करने से यह पक्का होता है कि हर बार
फिर से कॉम्पोज़ करने के बाद इफ़ेक्ट लागू हो जाएगा. दूसरी ओर, फिर से कॉम्पोज़ करने की प्रक्रिया पूरी होने से पहले कोई इफ़ेक्ट लागू करना गलत है. ऐसा तब होता है, जब इफ़ेक्ट को सीधे किसी कॉम्पोज़ेबल में लिखा जाता है.
उदाहरण के लिए, आपकी Analytics लाइब्रेरी की मदद से, बाद में होने वाले सभी Analytics इवेंट में कस्टम मेटाडेटा ("उपयोगकर्ता प्रॉपर्टी") अटैच करके, उपयोगकर्ताओं को सेगमेंट में बांटा जा सकता है. अपनी ऐनलिटिक्स लाइब्रेरी में मौजूद मौजूदा उपयोगकर्ता के टाइप की जानकारी देने के लिए, SideEffect
का इस्तेमाल करके उसकी वैल्यू अपडेट करें.
@Composable fun rememberFirebaseAnalytics(user: User): FirebaseAnalytics { val analytics: FirebaseAnalytics = remember { FirebaseAnalytics() } // On every successful composition, update FirebaseAnalytics with // the userType from the current User, ensuring that future analytics // events have this metadata attached SideEffect { analytics.setUserProperty("userType", user.userType) } return analytics }
produceState
: Compose स्टेटस में न होने वाले आइटम को Compose स्टेटस में बदलना
produceState
कॉम्पोज़िशन के स्कोप वाला कोरूटीन लॉन्च करता है, जो रिटर्न की गई State
में वैल्यू को पुश कर सकता है. इसका इस्तेमाल करके, 'लिखें' मोड में न होने वाली स्थिति को 'लिखें' मोड में बदलें. उदाहरण के लिए, बाहरी सदस्यता से जुड़ी स्थिति, जैसे कि Flow
, LiveData
या RxJava
को कॉम्पोज़िशन में शामिल करना.
produceState
के कॉम्पोज़िशन में शामिल होने पर प्रोड्यूसर लॉन्च हो जाता है और कॉम्पोज़िशन से बाहर निकलने पर रद्द हो जाता है. लौटाई गई State
वैल्यू एक साथ दिखती है; एक ही वैल्यू सेट करने पर, फिर से कॉम्पोज़ नहीं किया जाएगा.
भले ही, produceState
एक कोरुटाइन बनाता है, लेकिन इसका इस्तेमाल डेटा के ऐसे सोर्स को मॉनिटर करने के लिए भी किया जा सकता है जो निलंबित नहीं होते. उस सोर्स की सदस्यता हटाने के लिए, awaitDispose
फ़ंक्शन का इस्तेमाल करें.
नीचे दिए गए उदाहरण में, नेटवर्क से इमेज लोड करने के लिए produceState
का इस्तेमाल करने का तरीका बताया गया है. loadNetworkImage
कॉम्पोज़ेबल फ़ंक्शन, State
दिखाता है. इसका इस्तेमाल दूसरे कॉम्पोज़ेबल में किया जा सकता है.
@Composable fun loadNetworkImage( url: String, imageRepository: ImageRepository = ImageRepository() ): State<Result<Image>> { // Creates a State<T> with Result.Loading as initial value // If either `url` or `imageRepository` changes, the running producer // will cancel and will be re-launched with the new inputs. return produceState<Result<Image>>(initialValue = Result.Loading, url, imageRepository) { // In a coroutine, can make suspend calls val image = imageRepository.load(url) // Update State with either an Error or Success result. // This will trigger a recomposition where this State is read value = if (image == null) { Result.Error } else { Result.Success(image) } } }
derivedStateOf
: एक या उससे ज़्यादा स्टेटस ऑब्जेक्ट को किसी दूसरे स्टेटस में बदलना
Compose में, हर बार जब निगरानी में रखे गए स्टेटस ऑब्जेक्ट या कॉम्पोज़ेबल इनपुट में बदलाव होता है, तो फिर से कॉम्पोज़ होता है. हो सकता है कि कोई स्टेटस ऑब्जेक्ट या इनपुट, यूज़र इंटरफ़ेस (यूआई) को अपडेट करने की ज़रूरत से ज़्यादा बार बदल रहा हो. इससे, यूआई को बार-बार फिर से कॉम्पोज़ करना पड़ता है.
जब किसी कॉम्पोज़ेबल में आपके इनपुट, फिर से कॉम्पोज़ करने की ज़रूरत से ज़्यादा बार बदल रहे हों, तो आपको derivedStateOf
फ़ंक्शन का इस्तेमाल करना चाहिए. ऐसा अक्सर तब होता है, जब कोई चीज़ बार-बार बदल रही हो, जैसे कि स्क्रोल की पोज़िशन. हालांकि, कॉम्पोज़ेबल को सिर्फ़ तभी उस पर प्रतिक्रिया देनी होती है, जब वह तय थ्रेशोल्ड को पार कर जाए. derivedStateOf
, Compose की नई स्थिति का एक ऑब्जेक्ट बनाता है. इस ऑब्जेक्ट को सिर्फ़ ज़रूरत के हिसाब से अपडेट किया जा सकता है. इस तरह, यह Kotlin FlowsdistinctUntilChanged()
ऑपरेटर की तरह ही काम करता है.
सही इस्तेमाल
यहां दिया गया स्निपेट, derivedStateOf
के इस्तेमाल का सही उदाहरण दिखाता है:
@Composable // When the messages parameter changes, the MessageList // composable recomposes. derivedStateOf does not // affect this recomposition. fun MessageList(messages: List<Message>) { Box { val listState = rememberLazyListState() LazyColumn(state = listState) { // ... } // Show the button if the first visible item is past // the first item. We use a remembered derived state to // minimize unnecessary compositions val showButton by remember { derivedStateOf { listState.firstVisibleItemIndex > 0 } } AnimatedVisibility(visible = showButton) { ScrollToTopButton() } } }
इस स्निपेट में, firstVisibleItemIndex
तब बदलता है, जब दिखने वाला पहला आइटम बदलता है. स्क्रोल करने पर, वैल्यू 0
, 1
, 2
, 3
, 4
, 5
वगैरह हो जाती है. हालांकि, वैल्यू को फिर से बनाने की ज़रूरत सिर्फ़ तब होती है, जब वैल्यू 0
से ज़्यादा हो.
अपडेट की फ़्रीक्वेंसी में इस अंतर का मतलब है कि यह derivedStateOf
के लिए इस्तेमाल का एक अच्छा उदाहरण है.
गलत इस्तेमाल
आम तौर पर, यह मान लिया जाता है कि दो Compose स्टेट ऑब्जेक्ट को आपस में जोड़ते समय, derivedStateOf
का इस्तेमाल करना चाहिए, क्योंकि "स्टेट का डेरिवेशन" किया जा रहा है. हालांकि, यह पूरी तरह से ओवरहेड है और ज़रूरी नहीं है, जैसा कि नीचे दिए गए स्निपेट में दिखाया गया है:
// DO NOT USE. Incorrect usage of derivedStateOf. var firstName by remember { mutableStateOf("") } var lastName by remember { mutableStateOf("") } val fullNameBad by remember { derivedStateOf { "$firstName $lastName" } } // This is bad!!! val fullNameCorrect = "$firstName $lastName" // This is correct
इस स्निपेट में, fullName
को उतनी ही बार अपडेट करना होगा जितनी बार firstName
और
lastName
को अपडेट करना होगा. इसलिए, कोई अतिरिक्त रीकंपोज़िशन नहीं हो रहा है और derivedStateOf
का इस्तेमाल करना ज़रूरी नहीं है.
snapshotFlow
: Compose की स्थिति को फ़्लो में बदलना
State<T>
ऑब्जेक्ट को कोल्ड फ़्लो में बदलने के लिए, snapshotFlow
का इस्तेमाल करें. snapshotFlow
इकट्ठा होने पर अपना ब्लॉक चलाता है और उसमें पढ़े गए State
ऑब्जेक्ट का नतीजा दिखाता है. जब snapshotFlow
ब्लॉक में पढ़े गए State
ऑब्जेक्ट में बदलाव होता है, तो अगर नई वैल्यू, उत्सर्जित की गई पिछली वैल्यू से बराबर नहीं होती है, तो फ़्लो अपने कलेक्टर को नई वैल्यू उत्सर्जित करेगा. यह व्यवहार, Flow.distinctUntilChanged
के व्यवहार से मिलता-जुलता है.
नीचे दिए गए उदाहरण में, एक साइड इफ़ेक्ट दिखाया गया है. यह तब रिकॉर्ड होता है, जब उपयोगकर्ता किसी सूची में पहले आइटम को स्क्रोल करके Analytics पर जाता है:
val listState = rememberLazyListState()
LazyColumn(state = listState) {
// ...
}
LaunchedEffect(listState) {
snapshotFlow { listState.firstVisibleItemIndex }
.map { index -> index > 0 }
.distinctUntilChanged()
.filter { it == true }
.collect {
MyAnalyticsService.sendScrolledPastFirstItemEvent()
}
}
ऊपर दिए गए कोड में, listState.firstVisibleItemIndex
को फ़्लो में बदला गया है, ताकि फ़्लो के ऑपरेटर का फ़ायदा लिया जा सके.
इफ़ेक्ट रीस्टार्ट करना
LaunchedEffect
, produceState
या
DisposableEffect
जैसे Compose में मौजूद कुछ इफ़ेक्ट, अलग-अलग संख्या में आर्ग्युमेंट, बटन का इस्तेमाल करते हैं. इनका इस्तेमाल, चल रहे इफ़ेक्ट को रद्द करने और नए बटन के साथ नया इफ़ेक्ट शुरू करने के लिए किया जाता है.
इन एपीआई का सामान्य फ़ॉर्मैट यह है:
EffectName(restartIfThisKeyChanges, orThisKey, orThisKey, ...) { block }
इस व्यवहार की बारीकियों की वजह से, अगर इफ़ेक्ट को फिर से शुरू करने के लिए इस्तेमाल किए गए पैरामीटर सही नहीं हैं, तो समस्याएं हो सकती हैं:
- इफ़ेक्ट को ज़रूरत से कम बार रीस्टार्ट करने पर, आपके ऐप्लिकेशन में गड़बड़ियां हो सकती हैं.
- ज़रूरत से ज़्यादा इफ़ेक्ट फिर से शुरू करने से, इफ़ेक्ट का असर कम हो सकता है.
आम तौर पर, कोड के इफ़ेक्ट ब्लॉक में इस्तेमाल किए गए बदलाव किए जा सकने वाले और बदलाव नहीं किए जा सकने वाले वैरिएबल को, इफ़ेक्ट कॉम्पोज़ेबल में पैरामीटर के तौर पर जोड़ा जाना चाहिए. इनके अलावा, इफ़ेक्ट को फिर से शुरू करने के लिए और पैरामीटर जोड़े जा सकते हैं. अगर किसी वैरिएबल में बदलाव करने पर, इफ़ेक्ट को फिर से शुरू नहीं करना है, तो वैरिएबल को rememberUpdatedState
में रैप किया जाना चाहिए. अगर वैरिएबल कभी भी बदलता नहीं है, क्योंकि इसे बिना किसी कुंजी वाले remember
में लपेटा गया है, तो आपको वैरिएबल को इफ़ेक्ट के लिए कुंजी के तौर पर पास करने की ज़रूरत नहीं है.
ऊपर दिखाए गए DisposableEffect
कोड में, इफ़ेक्ट के पैरामीटर के तौर पर, उसके ब्लॉक में इस्तेमाल किया गया lifecycleOwner
लिया जाता है. ऐसा इसलिए होता है, क्योंकि उनमें किसी भी तरह का बदलाव करने पर, इफ़ेक्ट फिर से शुरू हो जाता है.
@Composable
fun HomeScreen(
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
onStart: () -> Unit, // Send the 'started' analytics event
onStop: () -> Unit // Send the 'stopped' analytics event
) {
// These values never change in Composition
val currentOnStart by rememberUpdatedState(onStart)
val currentOnStop by rememberUpdatedState(onStop)
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
/* ... */
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}
currentOnStart
और currentOnStop
को DisposableEffect
के तौर पर इस्तेमाल करने की ज़रूरत नहीं है, क्योंकि rememberUpdatedState
के इस्तेमाल की वजह से, कॉम्पोज़िशन में उनकी वैल्यू कभी नहीं बदलती. अगर lifecycleOwner
को पैरामीटर के तौर पर पास नहीं किया जाता और वह बदल जाता है, तो HomeScreen
फिर से कॉम्पोज़ हो जाता है. हालांकि, DisposableEffect
को न तो हटाया जाता है और न ही फिर से शुरू किया जाता है. इससे समस्याएं आती हैं, क्योंकि उस बिंदु से आगे गलत lifecycleOwner
का इस्तेमाल किया जाता है.
कुंजियों के तौर पर कॉन्स्टेंट
true
जैसे किसी कॉन्स्टेंट को इफ़ेक्ट बटन के तौर पर इस्तेमाल किया जा सकता है, ताकि वह कॉल साइट के लाइफ़साइकल को फ़ॉलो कर सके. हालांकि, इसके इस्तेमाल के कुछ मान्य उदाहरण हैं, जैसे कि ऊपर दिखाया गया LaunchedEffect
उदाहरण. हालांकि, ऐसा करने से पहले, अच्छी तरह सोच लें और पक्का करें कि आपको यही चाहिए.
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक टेक्स्ट दिखता है
- स्टेट और Jetpack Compose
- Jetpack Compose के लिए Kotlin
- 'लिखें' सुविधा में व्यू का इस्तेमाल करना