首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android AsyncTask 中優雅取消 HttpURLConnection 請求

     編輯:程式設計綜合問答

場景

用戶點擊「下載/請求」,啟動 AsyncTask 執行耗時 HTTP 請求。用戶點擊「取消」按鈕需立即中斷連接、釋放資源。

核心模式:持有連接引用 + disconnect()

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
        }
    }
}

Activity 中綁定按鈕

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 + Coroutines / RxJava

// 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 享受一行代碼取消。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved