एंड्रॉइड में AsyncTask कैंसिल करना — सही तरीका और आधुनिक विकल्प
AsyncTask एंड्रॉइड का पुराना बैकग्राउंड टास्क API है जो **API 30 (Android 11) में डिप्रिकेटेड** हो चुका है। फिर भी, लिगेसी कोडबेस में इसे कैंसिल करना आना ज़रूरी है। सही तरीका: cancel(true) कॉल करें और doInBackground में isCancelled() चेक करें।
⚠️ महत्वपूर्ण: AsyncTask डिप्रिकेटेड है
Google आधिकारिक तौर पर Coroutines (Kotlin), RxJava, या ExecutorService उपयोग करने की सिफारिश करता है। नए प्रोजेक्ट्स में AsyncTask न लिखें। यह ट्यूटोरियल केवल मौजूदा कोड समझने/मेंटेन करने के लिए है।
चरण 1: नया प्रोजेक्ट बनाएं
Android Studio → File → New → New Project → "Empty Activity" → Finish।
चरण 2: Layout (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="24dp"
android:gravity="center">
<Button
android:id="@+id/btnStart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="टास्क शुरू करें"
android:layout_marginBottom="16dp" />
<Button
android:id="@+id/btnCancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="टास्क रद्द करें"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/tvStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="16sp"
android:lineSpacingExtra="4dp"
android:text="तैयार" />
</LinearLayout>
चरण 3: MainActivity.java — सही कैंसिलेशन पैटर्न
package com.example.asynctaskcancel;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private Button btnStart, btnCancel;
private TextView tvStatus;
private DownloadTask currentTask; // वर्तमान टास्क रेफरेंस
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = findViewById(R.id.btnStart);
btnCancel = findViewById(R.id.btnCancel);
tvStatus = findViewById(R.id.tvStatus);
btnStart.setOnClickListener(v -> {
tvStatus.setText("");
currentTask = new DownloadTask();
currentTask.execute("Task 1", "Task 2", "Task 3", "Task 4", "Task 5");
});
btnCancel.setOnClickListener(v -> {
if (currentTask != null && currentTask.getStatus() == AsyncTask.Status.RUNNING) {
currentTask.cancel(true); // true = इंटरप्ट थ्रेड
appendStatus("🛑 कैंसिल रिक्वेस्ट भेजा गया...\n", Color.RED);
} else {
appendStatus("⚠️ कोई रनिंग टास्क नहीं\n", Color.GRAY);
}
});
}
private void appendStatus(String text, int color) {
tvStatus.append(text);
tvStatus.setTextColor(color);
}
// ===== AsyncTask सबक्लास =====
private class DownloadTask extends AsyncTask<String, Integer, List<String>> {
@Override
protected void onPreExecute() {
appendStatus("▶️ टास्क शुरू हो रहा है...\n", Color.BLUE);
}
@Override
protected List<String> doInBackground(String... tasks) {
List<String> completed = new ArrayList<>();
int total = tasks.length;
for (int i = 0; i < total; i++) {
// 🛑 कैंसिलेशन चेक — सबसे महत्वपूर्ण!
if (isCancelled()) {
break; // लूप छोड़ें, onCancelled() जाएगा
}
String task = tasks[i];
completed.add(task);
// काम सिमुलेट करें
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// इंटरप्ट हुआ — कैंसिलेशन का संकेत
Thread.currentThread().interrupt(); // इंटरप्ट फ्लैग रीस्टोर करें
break;
}
// प्रोग्रेस अपडेट (0-100%)
int progress = (int) (((i + 1) / (float) total) * 100);
publishProgress(progress);
}
return completed;
}
@Override
protected void onProgressUpdate(Integer... values) {
appendStatus("📊 प्रोग्रेस: " + values[0] + "%\n", Color.BLACK);
}
@Override
protected void onCancelled() {
appendStatus("❌ ऑपरेशन रद्द कर दिया गया\n", Color.RED);
}
@Override
protected void onPostExecute(List<String> result) {
if (!isCancelled()) { // डबल चेक
appendStatus("✅ पूरा हुआ! कार्य:\n", Color.GREEN);
for (String task : result) {
appendStatus(" • " + task + "\n", Color.DKGRAY);
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// एक्टिविटी डिस्ट्रॉय होने पर टास्क कैंसिल करें
if (currentTask != null && currentTask.getStatus() == AsyncTask.Status.RUNNING) {
currentTask.cancel(true);
}
}
}
चरण 4: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.asynctaskcancel">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AsyncTaskCancel">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
चलाएं और टेस्ट करें
- "टास्क शुरू करें" दबाएं — प्रोग्रेस 0% से 100% तक जाएगा।
- बीच में "टास्क रद्द करें" दबाएं — टास्क तुरंत रुकेगा, "रद्द" मैसेज दिखेगा।
- दोबारा शुरू करें — नया टास्क चलेगा।
🔑 AsyncTask कैंसिलेशन के गोल्डन नियम
cancel(true)कॉल करें —trueका अर्थ हैThread.interrupt()कॉल होगा।doInBackgroundमें **नियमित रूप से**isCancelled()चेक करें — खासकर लूप में।InterruptedExceptionपकड़ें औरThread.currentThread().interrupt()कॉल करें — इंटरप्ट स्टेटस बनाए रखने के लिए।onCancelled()में UI क्लीनअप करें — यह मेन थ्रेड पर चलता है।onPostExecuteमें भीisCancelled()चेक करें — रेस कंडीशन से बचने के लिए।
🚀 आधुनिक विकल्प: Coroutines (Kotlin) — स्ट्रक्चर्ड कंकरेंसी
// ViewModel में
private val job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.IO + job)
fun startDownload() {
scope.launch {
try {
val tasks = listOf("Task 1", "Task 2", "Task 3", "Task 4", "Task 5")
tasks.forEachIndexed { index, task ->
ensureActive() // 🛑 कैंसिलेशन चेक — ऑटोमैटिक
delay(1000) // सस्पेंड फंक्शन — इंटरप्टेबल
_progress.postValue((index + 1) * 100 / tasks.size)
}
_result.postValue(tasks)
} catch (e: CancellationException) {
_status.postValue("रद्द किया गया")
throw e // री-थ्रो ताकि पैरेंट कैंसिल हो
}
}
}
fun cancel() {
job.cancel() // सभी चाइल्ड कोरूटीन कैंसिल हो जाएंगे
job.join() // वैकल्पिक: पूरा होने तक वेट करें
}
🚀 आधुनिक विकल्प: ExecutorService + Future (Java)
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<List<String>> future = executor.submit(() -> {
List<String> result = new ArrayList<>();
for (String task : tasks) {
if (Thread.currentThread().isInterrupted()) break; // चेक
result.add(task);
Thread.sleep(1000);
}
return result;
});
// कैंसिल करने के लिए
future.cancel(true); // इंटरप्ट भेजता है
// शटडाउन
executor.shutdown();
सारांश
- 🚫 **नए कोड में AsyncTask न लिखें** — डिप्रिकेटेड, लीक-प्रोन, सीमित।
- ✅ **लिगेसी कोड के लिए**:
cancel(true)+isCancelled()चेक +InterruptedExceptionहैंडलिंग। - ✅ **Kotlin नए प्रोजेक्ट्स**: Coroutines + Structured Concurrency — बिल्ट-इन कैंसिलेशन, टेस्टेबल, लीक-फ्री।
- ✅ **Java नए प्रोजेक्ट्स**: ExecutorService + Future या RxJava।