परिचय: जेटपैक कम्पोज़ में कॉन्टेक्स्ट शुरुआती लोगों के लिए सिरदर्द क्यों है?
\nयदि आपने कभी XML का उपयोग करके Android पर लिखा है, तो आप जानते हैं कि Context वस्तुतः हर चीज़ की «कुंजी» है: संसाधनों तक पहुँचने से लेकर नई गतिविधियाँ शुरू करने तक। लेकिन जब आप Jetpack Compose पर स्विच करते हैं, तो सब कुछ बदल जाता है। कम्पोज़िट फ़ंक्शन के पास Context तक सीधी पहुँच नहीं होती है, और यह अक्सर डेवलपर्स के लिए, विशेष रूप से उन लोगों के लिए जो अभी-अभी घोषणात्मक दृष्टिकोण सीखना शुरू कर रहे हैं, एक बाधा बन जाता है।
Stack Overflow पर प्रश्न «How to get Context in Jetpack Compose» ने हज़ारों व्यूज़ और दर्जनों उत्तर एकत्र किए हैं। यह कोई संयोग नहीं है। इस लेख में, हम Compose में Context प्राप्त करने के सभी संभावित तरीकों पर चर्चा करेंगे, सरल से लेकर उन्नत तक, Kotlin में वास्तविक कोड उदाहरणों के साथ। आप जानेंगे कि LocalContext.current का उपयोग कब करना है, मेमोरी लीक से कैसे बचना है, और 2025 में किन प्रथाओं को «best practices» माना जाता है।
1. सबसे आसान तरीका: LocalContext.current
\nयदि आपको कम्पोज़िट फ़ंक्शन के अंदर Context प्राप्त करने की आवश्यकता है, तो सबसे सीधा तरीका LocalContext.current का उपयोग करना है। यह एक composable-लोकल है जो वर्तमान Context प्रदान करता है (आमतौर पर यह Activity या ContextWrapper होता है)।
@Composable\nfun MyScreen() {\n val context = LocalContext.current\n \n Button(onClick = {\n Toast.makeText(context, "कम्पोज़ से नमस्ते!", Toast.LENGTH_SHORT).show()\n }) {\n Text("Toast दिखाएँ")\n }\n}\n\nयह कोड काम करता है, लेकिन एक बारीक बात है: LocalContext.current आपको वह Context देता है जो वर्तमान CompositionLocal से जुड़ा होता है। अधिकांश मामलों में, यही वह है जो आपको चाहिए। हालाँकि, याद रखें कि ऐसे Context को ViewModel में पास नहीं किया जाना चाहिए या लंबे समय तक जीवित रहने वाली वस्तुओं में संग्रहीत नहीं किया जाना चाहिए - इससे मेमोरी लीक हो सकती है।
इसका उपयोग कब करें?
\n- \n
- UI में एकमुश्त कार्यों के लिए: Toast, Snackbar, Activity शुरू करना। \n
- संसाधनों तक पहुँचने के लिए:
context.getString(R.string.app_name)। \n - सिस्टम सेवाओं के साथ काम करने के लिए:
context.getSystemService()। \n
2. ViewModel में कॉन्टेक्स्ट: सही दृष्टिकोण
\nसबसे आम गलतियों में से एक है Context को सीधे ViewModel में पास करना। Android Architecture Components में इसे एक एंटी-पैटर्न माना जाता है, क्योंकि ViewModel Activity से अधिक समय तक जीवित रह सकता है, और Context पुराना हो जाएगा। इसके बजाय, AndroidViewModel का उपयोग करें।
class MyViewModel(application: Application) : AndroidViewModel(application) {\n \n private val context = getApplication<Application>().applicationContext\n \n fun loadData() {\n // applicationContext का उपयोग करें, जो सुरक्षित है\n val prefs = context.getSharedPreferences("my_prefs", Context.MODE_PRIVATE)\n }\n}\n\nCompose में, आप इस तरह के ViewModel का इंस्टेंस मानक तरीके से प्राप्त कर सकते हैं:
\n\n@Composable\nfun MyScreen() {\n val viewModel: MyViewModel = viewModel()\n // Context पहले से ही ViewModel के अंदर है, UI से पास करने की आवश्यकता नहीं है\n}\n\nलाभ: applicationContext तब तक जीवित रहता है जब तक प्रक्रिया जीवित है, और यह Activity के जीवनचक्र पर निर्भर नहीं करता है। यह सुरक्षित है और Google द्वारा अनुशंसित है।
3. CompositionLocal में कॉन्टेक्स्ट: कस्टम प्रदाता
\nकभी-कभी आपको एक विशिष्ट Context पास करने की आवश्यकता होती है (उदाहरण के लिए, परीक्षण के लिए या किसी लाइब्रेरी वाले मॉड्यूल के लिए)। ऐसे मामलों में, आप अपना स्वयं का CompositionLocal बना सकते हैं।
val LocalCustomContext = staticCompositionLocalOf<Context> {\n error("कोई कस्टम कॉन्टेक्स्ट प्रदान नहीं किया गया")\n}\n\n@Composable\nfun CustomContextProvider(context: Context, content: @Composable () -> Unit) {\n CompositionLocalProvider(LocalCustomContext provides context) {\n content()\n }\n}\n\n// उपयोग:\n@Composable\nfun MyScreen() {\n val customContext = LocalCus