वह सुबह जो NetworkOnMainThreadException से शुरू होती है
\n\nआप Android पर एक ऐप लिख रहे हैं। सब कुछ ठीक चल रहा है, जब तक आप एक बटन में एक साधारण HTTP अनुरोध करने का निर्णय नहीं लेते। आप "अपडेट करें" दबाते हैं — और ऐप लाल स्टैक के साथ क्रैश हो जाता है। परिचित लग रहा है? android.os.NetworkOnMainThreadException — यह एक क्लासिक त्रुटि है जिसे हर Android डेवलपर ने अपने जीवन में कम से कम एक बार देखा है। 2025 में यह अभी भी जीवित है, और नए लोग उसी गलती को दोहराते रहते हैं।
\n\nइस लेख में, हम समझेंगे कि NetworkOnMainThreadException क्यों होता है, Java में इसे कैसे ठीक करें, और 2025 में किन दृष्टिकोणों को सर्वोत्तम प्रथाएँ माना जाता है। आपको कोड के साथ तैयार समाधान मिलेंगे जिन्हें आप सीधे अपने प्रोजेक्ट में डाल सकते हैं।
\n\nNetworkOnMainThreadException क्यों होता है?
\n\nAndroid सिर्फ Java नहीं है। यह सख्त नियमों वाली एक प्रणाली है। उनमें से एक: मुख्य (UI) थ्रेड में नेटवर्क ऑपरेशन न करें। मुख्य थ्रेड इंटरफ़ेस को रेंडर करने और टच को संभालने के लिए जिम्मेदार है। यदि यह एक सेकंड के लिए भी ब्लॉक हो जाता है, तो उपयोगकर्ता "लैग" देखेगा, और यदि पाँच सेकंड के लिए, तो सिस्टम "ऐप प्रतिसाद नहीं दे रहा है" (ANR) डायलॉग दिखाएगा।
\n\nAndroid 3.0 (Honeycomb) से शुरू करके, Google ने एक सुरक्षा जोड़ी: मुख्य थ्रेड में कोई भी नेटवर्क कॉल android.os.NetworkOnMainThreadException फेंकता है। यह अपवाद कहता है: "अरे, तुम UX के लिए कुछ खतरनाक कर रहे हो!"।
2025 में यह नियम कहीं नहीं गया है। भले ही आप आधुनिक लाइब्रेरी (Retrofit, OkHttp) का उपयोग कर रहे हों, फिर भी आपको उन्हें पृष्ठभूमि थ्रेड में चलाना होगा। अपवाद कोई बग नहीं है, बल्कि एक सुरक्षा सुविधा है।
\n\nत्रुटि को ठीक करने के शीर्ष 5 तरीके (Java, 2025)
\n\nहम पाँच दृष्टिकोणों पर विचार करेंगे — पुराने से लेकर आधुनिक तक। वह चुनें जो आपके प्रोजेक्ट के लिए उपयुक्त हो।
\n\n1. क्लासिक AsyncTask (लेगसी, लेकिन काम करता है)
\n\nAsyncTask लगभग 10 साल पहले मानक था। 2025 में इसका उपयोग करने की अनुशंसा नहीं की जाती है (यह API 30+ में deprecated है), लेकिन पुराने प्रोजेक्ट्स पर आप अभी भी इससे मिल सकते हैं।
\n\nprivate class MyNetworkTask extends AsyncTask<String, Void, String> {\n @Override\n protected String doInBackground(String... params) {\n // यह पहले से ही पृष्ठभूमि थ्रेड है\n try {\n URL url = new URL(params[0]);\n HttpURLConnection connection = (HttpURLConnection) url.openConnection();\n BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));\n StringBuilder result = new StringBuilder();\n String line;\n while ((line = reader.readLine()) != null) {\n result.append(line);\n }\n return result.toString();\n } catch (Exception e) {\n return "Error: " + e.getMessage();\n }\n }\n\n @Override\n protected void onPostExecute(String result) {\n // यह पहले से ही UI थ्रेड है\n textView.setText(result);\n }\n}\n\n// शुरू करें:\nnew MyNetworkTask().execute("https://api.example.com/data");\n\nनुकसान: AsyncTask का परीक्षण करना कठिन है, यह अनुरोधों की श्रृंखला के लिए सुविधाजनक नहीं है, और स्क्रीन रोटेशन की स्थिति में मेमोरी लीक हो सकती है। इसका उपयोग केवल तभी करें जब प्रोजेक्ट Java 7-8 में लिखा गया हो।
\n\n2. Java Thread + Handler (स्वच्छ दृष्टिकोण)
\n\nसबसे सरल तरीका — एक अलग थ्रेड बनाएं और Handler के माध्यम से परिणाम UI पर वापस लाएं।
\n\nprivate Handler mainHandler = new Handler(Looper.getMainLooper());\n\nprivate void fetchDataInBackground() {\n new Thread(new Runnable() {\n @Override\n public void run() {\n // पृष्ठभूमि थ्रेड\n final String result = performNetworkCall();\n \n // UI थ्रेड पर वापस आएं\n mainHandler.post(new Runnable() {\n @Override\n public void run() {\n textView.setText(result);\n }\n });\n }\n }).start();\n}\n\nprivate String performN