Kotlin फ़्रैगमेंट में NullPointerException: कैसे जीतें और पागल न हों

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

प्रस्तावना: "मैंने ट्यूटोरियल के अनुसार सब कुछ किया, लेकिन ऐप क्रैश हो रहा है!"

\n

यदि आपने Kotlin पर Android डेवलपमेंट में अपनी यात्रा अभी शुरू की है, तो आपने शायद इस क्षण का सामना किया होगा। आप कोड लिखते हैं, ट्यूटोरियल का पालन करते हैं, ऐप लॉन्च करते हैं... और क्रैश। लॉग में — प्रसिद्ध java.lang.NullPointerException (या इसका Kotlin समकक्ष)। और हस्ताक्षर: "Cannot read field… because the view is null" (फ़ील्ड नहीं पढ़ सकता... क्योंकि व्यू शून्य है)।

\n

यह एक वास्तविक दर्द है जिसने Stack Overflow पर हज़ारों व्यूज़ एकत्र किए हैं। आज हम इसे हमेशा के लिए समझेंगे। Kotlin पर Fragment में View तक पहुँचने पर NullPointerException क्यों होता है? और, सबसे महत्वपूर्ण बात, इसे कैसे ठीक करें ताकि आप चैन से सो सकें।

\n

चलिए शुरू करते हैं!

\n\n

त्रुटि क्यों होती है? बुराई की जड़ — Lifecycle (जीवनचक्र)

\n

मुख्य कारण जिसके कारण शुरुआती लोगों को Kotlin Fragment में NullPointerException मिलता है, वह है फ़्रैगमेंट के जीवनचक्र की समझ की कमी। Activity में सब कुछ सरल है: onCreate — और आगे बढ़ें। Fragment में सब कुछ अधिक पेचीदा है।

\n

फ़्रैगमेंट कई चरणों से गुज़रता है:

\n
    \n
  • onCreateView() — यहाँ लेआउट इन्फ्लेट (बनाया) जाता है।
  • \n
  • onViewCreated() — यहाँ View पहले से मौजूद है।
  • \n
  • onDestroyView() — View नष्ट हो जाता है (उदाहरण के लिए, स्क्रीन घुमाने पर)।
  • \n
\n

सबसे लोकप्रिय त्रुटि — फ़्रैगमेंट द्वारा अपना लेआउट बनाने से पहले View तक पहुँचने का प्रयास करना। उदाहरण के लिए, कंस्ट्रक्टर में या फ़्रैगमेंट के onCreate() में। इस समय view null के बराबर है — इसलिए क्रैश होता है।

\n

दूसरा कारण — रेफरेंस लीक। आपने View का रेफरेंस एक वेरिएबल में सेव किया, और फिर फ़्रैगमेंट फिर से बन गया, और पुराना रेफरेंस कहीं नहीं जाता।

\n\n

विशिष्ट उदाहरण: कोड में समस्या कैसी दिखती है

\n

कल्पना करें कि आपके पास टेक्स्ट फ़ील्ड वाला एक सरल फ़्रैगमेंट है:

\n
class MyFragment : Fragment() {\n\n    private lateinit var myTextView: TextView\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        // त्रुटि! यहाँ अभी तक view मौजूद नहीं है\n        myTextView = requireView().findViewById(R.id.my_text_view)\n        myTextView.text = "नमस्ते!"\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        return inflater.inflate(R.layout.fragment_my, container, false)\n    }\n}
\n

यह कोड NullPointerException के साथ क्रैश होगा, क्योंकि onCreate() में requireView() null लौटाता है। View अभी तक नहीं बना है!

\n\n

त्रुटि को ठीक करने के 3 कार्यशील तरीके

\n

आइए तीन दृष्टिकोणों पर नज़र डालें जो Fragment में View तक पहुँचने की समस्या को गारंटी के साथ हल करेंगे।

\n\n

तरीका 1: कोड को onViewCreated() में ले जाएँ

\n

सबसे सरल और सही तरीका — उस क्षण की प्रतीक्षा करना जब View निश्चित रूप से मौजूद हो। onViewCreated() मेथड लेआउट बनने के तुरंत बाद कॉल किया जाता है।

\n
class MyFragment : Fragment() {\n\n    private lateinit var myTextView: TextView\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        return inflater.inflate(R.layout.fragment_my, container, false)\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        // अब view निश्चित रूप से null नहीं है!\n        myTextView = view.findViewById(R.id.my_text_view)\n        myTextView.text = "सब कुछ काम कर रहा है!"\n    }\n}
\n

लाभ: सरल, स्पष्ट, हमेशा काम करता है।
\nनुकसान: lateinit var के बारे में याद रखना होगा और onDestroyView() में रेफरेंस को शून्य करना नहीं भूलना होगा (अन्यथा मेमोरी लीक संभव है)।

\n\n

तरीका 2: View Binding का उपयोग करें (अनुशंसित)

\n

ब्लॉग

पुस्तक अनुशंसाएँ