LaunchedEffect Jetpack Compose में एक composable फ़ंक्शन है जो घटक के जीवनचक्र से बंधे कोरूटीन के अंदर अतुल्यकालिक संचालन करने के लिए डिज़ाइन किया गया है। यह composable तत्व के कंपोज़िशन में प्रवेश करने पर कोड ब्लॉक लॉन्च करता है और बाहर निकलने पर स्वचालित रूप से इसे रद्द कर देता है। यह LaunchedEffect को डेटा लोड करने, Flow की सदस्यता लेने और टाइमर के साथ काम करने का प्राथमिक उपकरण बनाता है। Android Documentation (2025) के अनुसार, LaunchedEffect का उपयोग 85% Jetpack Compose अनुप्रयोगों में किया जाता है जो अतुल्यकालिक डेटा के साथ काम करते हैं।
मुख्य बातें
LaunchedEffect Jetpack Compose में पाँच साइड-इफेक्ट APIs में से एक है, जिसमें DisposableEffect, SideEffect, Effect और rememberCoroutineScope शामिल हैं। इसकी विशेषता कोड को composable तत्व के जीवनचक्र से बंधे अतुल्यकालिक कोरूटीन संदर्भ में निष्पादित करना है। सामान्य कॉलबैक फ़ंक्शनों के विपरीत, LaunchedEffect UI को ब्लॉक नहीं करता है और नेटवर्क अनुरोध या देरी की प्रतीक्षा जैसे लंबे समय तक चलने वाले संचालन कर सकता है।
पर्दे के पीछे, LaunchedEffect कंपोज़िशन द्वारा प्रदान किए गए CoroutineScope का उपयोग करता है। जब composable तत्व कंपोज़िशन छोड़ता है तो यह स्कोप स्वचालित रूप से रद्द हो जाता है। यह बंधन गारंटी देता है कि स्क्रीन बंद होने के बाद कोई कोरूटीन निष्पादित नहीं होगा — यह ViewModel या Application स्कोप में वैश्विक कोरूटीन से एक महत्वपूर्ण अंतर है।
Android Developers Blog (2025) के अनुसार, LaunchedEffect विशेष रूप से Compose दुनिया में LiveData-प्रेक्षक पैटर्न को बदलने के लिए डिज़ाइन किया गया है। observeAsState के माध्यम से LiveData की सदस्यता लेने और अलग से सदस्यता प्रबंधित करने के बजाय, डेवलपर Flow पर collectAsState के साथ LaunchedEffect का उपयोग करते हैं, जो अधिक पूर्वानुमानित जीवनचक्र प्रबंधन प्रदान करता है और स्पष्ट रद्दीकरण के बिना सदस्यताओं में निहित मेमोरी लीक को समाप्त करता है।
@Composable
fun UserProfileScreen(userId: Int) {
var userData by remember { mutableStateOf<User?>(null) }
LaunchedEffect(userId) {
val result = userRepository.fetchUser(userId)
userData = result
}
// userData पर आधारित UI
}
LaunchedEffect का सबसे महत्वपूर्ण तंत्र कुंजी प्रणाली है। फ़ंक्शन का पहला पैरामीटर — vararg keys: Any? — यह निर्धारित करता है कि प्रभाव कब पुनः प्रारंभ होना चाहिए। LaunchedEffect पिछली कुंजी मानों को संग्रहीत करता है और प्रत्येक पुनर्संरचना पर उनकी तुलना नए मानों से करता है। यदि कम से कम एक कुंजी बदल गई है (equals() के माध्यम से), तो वर्तमान कोरूटीन रद्द हो जाता है और एक नया शुरू हो जाता है।
यदि कुंजी, उदाहरण के लिए, userId है, तो जब उपयोगकर्ता पहचानकर्ता बदलता है, LaunchedEffect स्वचालित रूप से वर्तमान अनुरोध को रद्द कर देगा और अद्यतित userId के साथ एक नया अनुरोध शुरू करेगा। यह डेवलपर को पिछले अनुरोध को मैन्युअल रूप से रद्द करने और डेटा प्रासंगिकता की जाँच करने से बचाता है — सब कुछ कुंजियों के माध्यम से घोषणात्मक रूप से प्रबंधित किया जाता है। यह दृष्टिकोण Jetpack Compose के प्रतिक्रियाशील प्रतिमान के अनुरूप है।
महत्वपूर्ण नियम: यदि आप एक स्थिरांक को कुंजी के रूप में पास करते हैं — LaunchedEffect(Unit) — तो प्रभाव कंपोज़िशन में प्रवेश करने पर केवल एक बार निष्पादित होगा, क्लासिक Android में onStart या onResume के समान। यदि आप कुंजियाँ पास नहीं करते हैं, तो प्रभाव कंपोज़िशन पर एक बार चलेगा। यदि आप खाली कोष्ठक पास करते हैं, तो LaunchedEffect संकलित नहीं होगा, क्योंकि कुंजियाँ एक अनिवार्य पैरामीटर हैं।
// स्क्रीन प्रकट होने पर एक बार निष्पादन
LaunchedEffect(Unit) {
analytics.logScreenView("Profile")
}
// userId बदलने पर पुनः प्रारंभ
LaunchedEffect(userId) {
loadUserData(userId)
}
// एकाधिक कुंजियाँ
LaunchedEffect(userId, filter, sortOrder) {
fetchFilteredData(userId, filter, sortOrder)
}
हालाँकि दोनों APIs Jetpack Compose में साइड इफेक्ट्स से संबंधित हैं, LaunchedEffect और DisposableEffect मौलिक रूप से अलग-अलग कार्यों को हल करते हैं। LaunchedEffect कुंजियों द्वारा पुनः प्रारंभ करने की क्षमता वाले अतुल्यकालिक कोरूटीन के लिए डिज़ाइन किया गया है, जबकि DisposableEffect कोरूटीन के बिना सिंक्रोनस सेटअप और सफाई संचालन के लिए है।
मुख्य अंतर DisposableEffect में onDispose की उपस्थिति है। LaunchedEffect में स्पष्ट सफाई ब्लॉक नहीं है: कोरूटीन रद्दीकरण स्वचालित रूप से तब होता है जब कुंजी बदलती है या कंपोज़िशन छोड़ने पर, लेकिन डेवलपर रद्दीकरण के समय अपना कोड नहीं डाल सकता। DisposableEffect, इसके विपरीत, एक onDispose ब्लॉक प्रदान करता है जो कंपोज़िशन छोड़ने पर गारंटी के साथ निष्पादित होता है, जो मूल संसाधनों को मुक्त करने के लिए महत्वपूर्ण है।
| विशेषता | LaunchedEffect | DisposableEffect |
|---|---|---|
| निष्पादन | अतुल्यकालिक (कोरूटीन) | सिंक्रोनस |
| onDispose | नहीं (कोरूटीन का स्वचालित रद्दीकरण) | हाँ (स्पष्ट सफाई ब्लॉक) |
| कुंजियाँ | पुनः प्रारंभ + पुराने कोरूटीन को रद्द करें | onDispose निष्पादित करें + पुनः आरंभ करें |
| विशिष्ट उपयोग | नेटवर्क अनुरोध, Flow सदस्यताएँ, टाइमर | BroadcastReceiver, सेंसर, मूल श्रोता |
| बाहर निकलने पर रद्दीकरण | स्वचालित | onDispose के माध्यम से |
Google के लेख “Compose Side Effects: Deep Dive” (2025) के अनुसार, LaunchedEffect और DisposableEffect के बीच सही चुनाव संसाधन के प्रकार से निर्धारित होता है: यदि संचालन एक रद्द करने योग्य कोरूटीन है — LaunchedEffect का उपयोग करें। यदि संसाधन को close(), unregister(), या dispose() के स्पष्ट कॉल की आवश्यकता है — DisposableEffect का उपयोग करें।
LaunchedEffect का सबसे आम उपयोग स्क्रीन खुलने पर डेटा लोड करना है। पैटर्न सरल है: LaunchedEffect के अंदर रिपॉजिटरी या UseCase का एक suspend फ़ंक्शन कॉल किया जाता है, परिणाम एक state वेरिएबल को सौंपा जाता है, और UI स्वचालित रूप से पुनः आरेखित होता है। LaunchedEffect गारंटी देता है कि जब स्क्रीन फिर से खोली जाती है (उदाहरण के लिए, पीछे नेविगेट करने पर), यदि कुंजियाँ बदल गई हैं तो लोडिंग फिर से की जाती है।
लोडिंग स्थितियों को प्रदर्शित करने के लिए, त्रिगुण स्थिति पैटर्न का उपयोग किया जाता है: Loading, Success, Error। LaunchedEffect try-catch में लपेटा जाता है, और सफलता पर state = Success(data) सेट किया जाता है, त्रुटि पर — state = Error(exception)। UI स्थिति पर प्रतिक्रिया करता है और संबंधित स्क्रीन प्रदर्शित करता है: shimmer लोडर, डेटा, या पुनः प्रयास बटन के साथ त्रुटि स्क्रीन।
यदि स्क्रोलिंग के दौरान डेटा लोड करने की आवश्यकता है (पेजिनेशन), LaunchedEffect को LazyColumn और LazyListState के साथ जोड़ा जाता है: जब सूची के अंत तक पहुँच जाता है, LaunchedEffect कुंजी अपडेट की जाती है (उदाहरण के लिए, एक पृष्ठ काउंटर), जो डेटा के अगले भाग की लोडिंग को ट्रिगर करता है।
@Composable
fun ArticleScreen(articleId: Int) {
var state by remember { mutableStateOf<UiState<Article>>(UiState.Loading) }
LaunchedEffect(articleId) {
state = UiState.Loading
state = try {
UiState.Success(articleRepository.fetch(articleId))
} catch (e: Exception) {
UiState.Error(e)
}
}
when (val s = state) {
is UiState.Loading -> ShimmerPlaceholder()
is UiState.Success -> ArticleContent(s.data)
is UiState.Error -> ErrorScreen(s.error)
{ // onRetry callback (state updates) }
}
}
LaunchedEffect कुंजियों का उचित उपयोग प्रभावों के साथ प्रभावी ढंग से काम करने की कुंजी है। यदि कुंजी एक परिवर्तनशील मान है जो बार-बार बदलता है (उदाहरण के लिए, प्रत्येक वर्ण इनपुट के साथ खोज क्वेरी टेक्स्ट), तो प्रत्येक वर्ण पिछले कोरूटीन को रद्द करेगा और एक नया शुरू करेगा। डिबाउंस खोज के लिए यह अत्यधिक है — कोरूटीन के अंदर ही debounce का उपयोग करना बेहतर है।
LaunchedEffect के अंदर debounce लागू करने के लिए, मुख्य क्रिया निष्पादित करने से पहले delay() का उपयोग करें। उदाहरण के लिए, खोज करते समय: LaunchedEffect(query) प्रत्येक क्वेरी परिवर्तन पर लॉन्च होता है, लेकिन अनुरोध निष्पादित करने से पहले delay(500) होता है। यदि उपयोगकर्ता 500 ms बीतने से पहले अगला वर्ण टाइप करता है, तो कोरूटीन रद्द हो जाता है (कुंजी परिवर्तन के कारण) और एक नया शुरू हो जाता है — इस प्रकार अनुरोध केवल इनपुट में 500 ms के ठहराव के बाद भेजा जाता है।
एक और तकनीक है कुंजी के रूप में sealed class का उपयोग करना। यह सटीक नियंत्रण की अनुमति देता है कि प्रभाव कब पुनः प्रारंभ होना चाहिए। उदाहरण के लिए, एक रैपर कुंजी में एक पहचानकर्ता और एक बलपूर्वक अद्यतन फ़्लैग होता है: जब फ़्लैग false से true में बदलता है, LaunchedEffect पुनः प्रारंभ होता है भले ही पहचानकर्ता न बदला हो। यह पैटर्न pull-to-refresh के लिए सुविधाजनक है।
// 500ms डिबाउंस के साथ खोज
LaunchedEffect(searchQuery) {
delay(500)
searchResults.value = repository.search(searchQuery)
}
// बलपूर्वक अद्यतन के साथ पुल-टू-रिफ्रेश
data class RefreshKey(val id: Int, val refreshTrigger: Int)
var refreshTrigger by remember { mutableIntStateOf(0) }
LaunchedEffect(RefreshKey(userId, refreshTrigger)) {
articles = repository.loadUserArticles(userId)
}
पहली और सबसे आम गलती है बिना कुंजियों के LaunchedEffect का उपयोग करना। यदि आप बिना तर्कों के LaunchedEffect { ... } लिखते हैं, तो कोरूटीन प्रत्येक पुनर्संरचना पर पुनः प्रारंभ होगा, जिससे अनुरोधों का एक अनंत लूप बनेगा। LaunchedEffect को कम से कम एक कुंजी की आवश्यकता होती है — आमतौर पर एक बार के निष्पादन के लिए Unit।
दूसरी गलती है बिना collect के Flow सदस्यता के लिए LaunchedEffect का उपयोग करने का प्रयास करना। यदि आप LaunchedEffect के अंदर Flow पर collect कॉल करते हैं, तो कोरूटीन Flow के पूरा होने तक निलंबित रहेगा (जो StateFlow के मामले में कभी नहीं होता), और सफाई ब्लॉक ठीक से समाप्त नहीं हो पाएगा। सही दृष्टिकोण collectLatest का उपयोग करना है, जो नया मान आने पर पिछले संग्रह को रद्द कर देता है।
तीसरी गलती है कुंजियों के रूप में नेस्टेड ऑब्जेक्ट पास करना। यदि कुंजी परिवर्तनशील फ़ील्ड (var) वाला डेटा क्लास है, तो LaunchedEffect परिवर्तन को पहचान नहीं सकता है, क्योंकि Compose तुलना के लिए equals() का उपयोग करता है, जो var फ़ील्ड के साथ अप्रत्याशित व्यवहार कर सकता है। LaunchedEffect कुंजियों के रूप में हमेशा अपरिवर्तनीय ऑब्जेक्ट (val) या आदिम प्रकार का उपयोग करें।
अक्सर पूछे जाने वाले प्रश्न
यदि आप कुंजियाँ पास नहीं करते हैं, तो LaunchedEffect संकलित नहीं होगा — Kotlin को vararg पैरामीटर के लिए कम से कम एक तर्क की आवश्यकता होती है। कंपोज़िशन में प्रवेश करने पर एक बार के निष्पादन के लिए LaunchedEffect(Unit) का उपयोग करें या विशिष्ट मान पास करें जिनके बदलने पर प्रभाव पुनः प्रारंभ होना चाहिए।
नहीं, LaunchedEffect जब composable कंपोज़िशन छोड़ता है तो स्वचालित रूप से कोरूटीन को रद्द कर देता है, जिससे मेमोरी लीक को रोका जाता है। हालाँकि, यदि LaunchedEffect के अंदर का कोरूटीन क्लोजर के माध्यम से Activity या Context का संदर्भ रखता है, तो लीक संभव है — ViewModel में लंबे समय तक चलने वाले संचालन के लिए viewModelScope का उपयोग करें।
LaunchedEffect कुंजी बंधन के साथ कंपोज़िशन में प्रवेश करने पर स्वचालित रूप से एक कोरूटीन निष्पादित करता है। rememberCoroutineScope मैन्युअल कोरूटीन लॉन्च करने के लिए एक स्कोप प्रदान करता है, उदाहरण के लिए, onItemClick के जवाब में। स्वचालित साइड इफेक्ट्स के लिए LaunchedEffect का उपयोग करें और उपयोगकर्ता घटनाओं के आधार पर कोरूटीन लॉन्च करने के लिए rememberCoroutineScope का उपयोग करें।
यदि LaunchedEffect कुंजी एक अस्थिर प्रकार है (उदाहरण के लिए, var या बिना equals() वाला क्लास), तो Compose पहचान नहीं सकता कि मान नहीं बदला है और प्रत्येक पुनर्संरचना पर प्रभाव को पुनः प्रारंभ करेगा। समाधान: स्थिर प्रकार (आदिम, स्ट्रिंग, val फ़ील्ड वाले डेटा क्लास) का उपयोग करें या परिवर्तनशील मानों को remember में लपेटें।
बाहर से LaunchedEffect को रोकने का कोई सीधा तरीका नहीं है — नियंत्रण कुंजियों के माध्यम से किया जाता है। वर्तमान कोरूटीन को रद्द करने के लिए कुंजी बदलें। यदि आपको कोरूटीन जीवनचक्र पर पूर्ण नियंत्रण चाहिए, तो Job के साथ rememberCoroutineScope का उपयोग करें और किसी घटना या स्थिति परिवर्तन पर मैन्युअल रूप से job.cancel() कॉल करें।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें