Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Android

एंड्रॉइड में AsyncTask थ्रेड कैसे रोकें? (और आधुनिक विकल्प)

एंड्रॉइड में 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>

चलाएं और टेस्ट करें

  1. "टास्क शुरू करें" दबाएं — प्रोग्रेस 0% से 100% तक जाएगा।
  2. बीच में "टास्क रद्द करें" दबाएं — टास्क तुरंत रुकेगा, "रद्द" मैसेज दिखेगा।
  3. दोबारा शुरू करें — नया टास्क चलेगा।

🔑 AsyncTask कैंसिलेशन के गोल्डन नियम

  1. cancel(true) कॉल करें — true का अर्थ है Thread.interrupt() कॉल होगा।
  2. doInBackground में **नियमित रूप से** isCancelled() चेक करें — खासकर लूप में।
  3. InterruptedException पकड़ें और Thread.currentThread().interrupt() कॉल करें — इंटरप्ट स्टेटस बनाए रखने के लिए।
  4. onCancelled() में UI क्लीनअप करें — यह मेन थ्रेड पर चलता है।
  5. 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।
  1. Android में ButterKnife लाइब्रेरी का उपयोग कैसे करें? Android में ButterKnife लाइब्रेरी का उपयोग कैसे करें?

    Android में ButterKnife से व्यू बाइंडिंग सरल बनाना ButterKnife एक व्यू बाइंडिंग लाइब्रेरी है जो findViewById() कॉल्स को एनोटेशन से बदल देती है। नोट: ButterKnife अब डिप्रिकेटेड है; आधुनिक ऐप्स के लिए View Binding (बिल्ट-इन) या Data Binding उपयोग करें। ⚠ डिप्रिकेटेड: Jake Wharton ने ButterKnife को म

  1. Android में JSON कैसे पार्स करें? Android में JSON कैसे पार्स करें?

    Android में JSONObject से सरल JSON पार्स करने का गाइड यह ट्यूटोरियल दिखाता है कि कैसे एक JSON स्ट्रिंग से JSONObject बनाकर नेस्टेड ऑब्जेक्ट्स से मान निकाले जाएं। चरण 1: नया प्रोजेक्ट बनाएं Android Studio में File → New Project चुनकर नया प्रोजेक्ट बनाएं। चरण 2: लेआउट फ़ाइल में कोड जोड़ें res/layout

  1. Android TextView में टेक्स्ट को जस्टिफाई कैसे करें? Android TextView में टेक्स्ट को जस्टिफाई कैसे करें?

    TextView में टेक्स्ट जस्टिफिकेशन Android 8.0 (API 26) से android:justificationMode=inter_word एट्रिब्यूट का उपयोग करके TextView में टेक्स्ट को जस्टिफाई (दोनों किनारों पर संरेखित) किया जा सकता है। चरण 1: नया प्रोजेक्ट बनाएं Android Studio में File → New Project चुनें (न्यूनतम API 26 या अधिक)। चरण 2