用戶點擊「下載/請求」,啟動 AsyncTask 執行耗時 HTTP 請求。用戶點擊「取消」按鈕需立即中斷連接、釋放資源。
public class HttpTask extends AsyncTask<String, Void, String> {
private HttpURLConnection connection; // 成員變量持有引用
private volatile boolean cancelled = false;
@Override
protected String doInBackground(String... urls) {
try {
URL url = new URL(urls[0]);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(10000);
connection.setReadTimeout(30000);
connection.setRequestMethod("GET");
// 關鍵:定期檢查取消標誌(在長耗時操作點)
if (cancelled) return null;
int responseCode = connection.getResponseCode();
if (cancelled) return null;
// 讀取流...
return readStream(connection.getInputStream());
} catch (IOException e) {
if (!cancelled) Log.e("HttpTask", "Request failed", e);
return null;
} finally {
if (connection != null) connection.disconnect(); // 確保釋放
}
}
// 供外部調用取消
public void cancelRequest() {
cancelled = true;
if (connection != null) {
connection.disconnect(); // 立即中斷底層 Socket
}
}
}
private HttpTask currentTask;
btnStart.setOnClickListener(v -> {
currentTask = new HttpTask();
currentTask.execute("https://api.example.com/data");
});
btnCancel.setOnClickListener(v -> {
if (currentTask != null) {
currentTask.cancelRequest(); // 自定義取消
currentTask.cancel(true); // 標準 AsyncTask.cancel(true) → doInBackground 返回
currentTask = null;
}
});
| 細節 | 說明 |
|---|---|
volatile boolean cancelled | 保證多線程可見性,doInBackground 定期輪詢 |
connection.disconnect() | 釋放 Socket、使 getInputStream() 拋出 InterruptedIOException,加速退出 |
finally 塊 | 正常/異常/取消三條路徑都釋放連接,防洩漏 |
| 避免在 UI 線程耗時 | 取消操作極快,直接調用 disconnect() 即可 |
// OkHttp 取消極簡
Call call = client.newCall(request).enqueue(callback);
// 取消
call.cancel(); // 內部自動關閉連接、回調 onFailure(IOException "Canceled")
新專案強烈建議遷移至 **OkHttp + Kotlin Coroutines** 或 **Retrofit + Flow**,AsyncTask 已棄用 (API 30)。
AsyncTask 取消 HTTP:**成員變量持有 HttpURLConnection → 自定義 cancelRequest() 呼叫 disconnect() → doInBackground 輪詢 cancelled 標誌 → finally 保證釋放**。遷移 OkHttp 享受一行代碼取消。