NetworkOnMainThreadException को ठीक करना
NetworkOnMainThreadException तब फेंका जाता है जब ऐप मुख्य (UI) थ्रेड पर नेटवर्क ऑपरेशन करने का प्रयास करता है। यह एंड्रॉइड 3.0 (हनीकॉम्ब) और उच्चतर पर लागू होता है।
❌ समस्या: मुख्य थ्रेड पर नेटवर्क कॉल
// गलत - यह क्रैश करेगा
URL url = new URL("https://example.com/data.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
String data = reader.readLine(); // मुख्य थ्रेड पर नेटवर्क I/O!
✅ समाधान 1: AsyncTask (डिप्रिकेटेड लेकिन सरल)
नोट: AsyncTask API 30 में डिप्रिकेटेड है। नए प्रोजेक्ट्स के लिए नीचे दिए गए आधुनिक विकल्प देखें।
चरण 1: लेआउट XML
res/layout/activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/textLoad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="लोड हो रहा है..."
android:textSize="12sp"
android:textStyle="bold|italic" />
<TextView
android:id="@+id/textMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
चरण 2: AsyncTask इम्प्लीमेंटेशन
MainActivity.java:
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private TextView textLoad, textMessage;
private static final String URL_STRING = "https://example.com/data.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textLoad = findViewById(R.id.textLoad);
textMessage = findViewById(R.id.textMessage);
textLoad.setText("लोड हो रहा है...");
new FetchDataTask().execute();
}
private class FetchDataTask extends AsyncTask {
@Override
protected String doInBackground(Void... voids) {
try {
URL url = new URL(URL_STRING);
BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream()));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
reader.close();
return result.toString();
} catch (IOException e) {
e.printStackTrace();
return "त्रुटि: " + e.getMessage();
}
}
@Override
protected void onPostExecute(String result) {
textMessage.setText(result);
textLoad.setText("पूर्ण");
}
}
}
✅ समाधान 2: Thread + Handler (बेसिक)
new Thread(() -> {
try {
URL url = new URL(URL_STRING);
BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream()));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
reader.close();
// UI अपडेट के लिए मुख्य थ्रेड पर वापस आएं
runOnUiThread(() -> {
textMessage.setText(result.toString());
textLoad.setText("पूर्ण");
});
} catch (IOException e) {
e.printStackTrace();
runOnUiThread(() -> textMessage.setText("त्रुटि: " + e.getMessage()));
}
}).start();
✅ समाधान 3: ExecutorService (अनुशंसित - जावा)
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private void fetchData() {
textLoad.setText("लोड हो रहा है...");
executor.execute(() -> {
try {
URL url = new URL(URL_STRING);
BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream()));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
reader.close();
runOnUiThread(() -> {
textMessage.setText(result.toString());
textLoad.setText("पूर्ण");
});
} catch (IOException e) {
e.printStackTrace();
runOnUiThread(() -> textMessage.setText("त्रुटि: " + e.getMessage()));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
executor.shutdown(); // संसाधन मुक्त करें
}
✅ समाधान 4: Kotlin Coroutines (आधुनिक मानक)
// build.gradle में:
// implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.0"
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.lifecycle.lifecycleScope
lifecycleScope.launch {
textLoad.text = "लोड हो रहा है..."
try {
val result = withContext(Dispatchers.IO) {
URL(URL_STRING).readText()
}
textMessage.text = result
textLoad.text = "पूर्ण"
} catch (e: Exception) {
textMessage.text = "त्रुटि: ${e.message}"
}
}
✅ समाधान 5: Retrofit/Volley/OkHttp (नेटवर्किंग लाइब्रेरी)
उत्पादन ऐप्स के लिए मजबूत नेटवर्किंग लाइब्रेरी का उपयोग करें:
// Retrofit उदाहरण
interface ApiService {
@GET("data.txt")
suspend fun getData(): Response
}
// उपयोग:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://example.com/")
.build();
ApiService service = retrofit.create(ApiService.class);
service.getData().enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
textMessage.setText(response.body());
textLoad.setText("पूर्ण");
}
@Override
public void onFailure(Call call, Throwable t) {
textMessage.setText("त्रुटि: " + t.getMessage());
}
});
चरण 3: Manifest में इंटरनेट अनुमति
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
<activity android:name=".MainActivity" android:exported="true">...</activity>
</application>
</manifest>
📋 सारांश: कौन सा उपयोग करें?
| दृष्टिकोण | उपयोग केस |
|---|---|
| Retrofit/OkHttp | उत्पादन ऐप्स, REST APIs, जटिल नेटवर्किंग |
| Kotlin Coroutines | आधुनिक कोटलिन ऐप्स, सरल एसिंक कार्य |
| ExecutorService | जावा ऐप्स, बैकग्राउंड थ्रेड पूल |
| WorkManager | डिफरेबल, गारंटीड बैकग्राउंड कार्य |
| AsyncTask | केवल लिगेसी कोड रखरखाव |
ऐप चलाएं
डिवाइस कनेक्ट करें, Run पर क्लिक करें। डेटा लोड होने पर "पूर्ण" और कंटेंट दिखाई देगा।