साइड-इफ़ेक्ट, ऐप्लिकेशन की स्थिति में होने वाले ऐसे बदलाव होता है जो कंपोज़ेबल फ़ंक्शन के दायरे से बाहर होता है. कंपोज़ेबल के लाइफ़साइकल और अचानक होने वाले रीकंपोज़िशन जैसी प्रॉपर्टी की वजह से, कंपोज़ेबल के रीकंपोज़िशन को अलग-अलग क्रम में लागू किया जाना चाहिए या खारिज किए जा सकने वाले कंपोज़िशन को साइड-इफ़ेक्ट नहीं होना चाहिए.
हालांकि, कभी-कभी साइड इफ़ेक्ट ज़रूरी होते हैं. उदाहरण के लिए, एक बार होने वाले इवेंट को ट्रिगर करने के लिए, जैसे कि स्नैकबार दिखाना या किसी खास स्थिति के हिसाब से किसी दूसरी स्क्रीन पर नेविगेट करना. इन कार्रवाइयों को ऐसे कंट्रोल किए गए एनवायरमेंट से कॉल किया जाना चाहिए जो कॉम्पोज़ेबल के लाइफ़साइकल के बारे में जानता हो. इस पेज पर, आपको Jetpack Compose के अलग-अलग साइड-इफ़ेक्ट एपीआई के बारे में जानकारी दी जाएगी.
स्टेट और इफ़ेक्ट के इस्तेमाल के उदाहरण
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
के साथ Compose का इस्तेमाल करें. SideEffect
का इस्तेमाल करने से यह गारंटी मिलती है कि हर बार बदलाव करने के बाद असर लागू हो जाएगा. दूसरी ओर, फिर से कॉम्पोज़ करने की प्रोसेस पूरी होने से पहले कोई इफ़ेक्ट लागू करना गलत है. ऐसा तब होता है, जब इफ़ेक्ट को सीधे किसी कॉम्पोज़ेबल में लिखा जाता है.
उदाहरण के लिए, आपकी Analytics लाइब्रेरी की मदद से, बाद में होने वाले सभी 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
: गैर-लिखें स्थिति को लिखें स्थिति में बदलें
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
: एक या उससे ज़्यादा स्टेटस ऑब्जेक्ट को किसी दूसरे स्टेटस में बदलना
कंपोज़िशन में, हर बार मॉनिटर किए जा सकने वाले स्टेट ऑब्जेक्ट या कंपोज़ेबल इनपुट में बदलाव होने पर रीकंपोज़िशन होती है. हो सकता है कि कोई स्टेटस ऑब्जेक्ट या इनपुट, यूज़र इंटरफ़ेस (यूआई) को अपडेट करने की ज़रूरत से ज़्यादा बार बदल रहा हो. इससे, यूआई को बार-बार फिर से कॉम्पोज़ करना पड़ता है.
आपको derivedStateOf
फ़ंक्शन का इस्तेमाल तब करना चाहिए, जब किसी कंपोज़ेबल में आपके इनपुट को रीकंपोज़ करने की ज़रूरत से ज़्यादा बार बदला जा रहा हो. ऐसा अक्सर तब होता है, जब कोई कॉन्टेंट बार-बार बदलता रहता है, जैसे कि स्क्रोल करने की जगह. हालांकि, कंपोज़ेबल को एक तय सीमा पार करने के बाद ही उस पर प्रतिक्रिया देनी होती है. derivedStateOf
एक नया कंपोज़ स्टेट ऑब्जेक्ट बनाता है,
जो आपको सिर्फ़ ज़रूरत के हिसाब से अपडेट देखने की सुविधा देता है. इस तरह यह, Kotlinflows
distinctUntilChanged()
ऑपरेटर की तरह ही काम करता है.
सही इस्तेमाल
नीचे दिया गया स्निपेट, 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
- 'लिखें' सुविधा में व्यू का इस्तेमाल करना