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

Android 4.0+ HttpClient 崩潰:網路請求必須在背景執行緒(AsyncTask/協程)

     編輯:程式設計綜合問答

問題現象

同樣的 DefaultHttpClient 程式碼在 Android 2.2/2.3 正常,4.0 (ICS) 以上崩潰。原因是 Android 3.0+ 強制執行 StrictMode,攔截主執行緒網路 I/O,拋出 NetworkOnMainThreadException。

錯誤程式碼

// 在 onCreate 直接執行網路請求
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://google.com");
HttpResponse response = httpclient.execute(httppost);  // 主執行緒阻塞,ICS+ 崩潰

正確解法:背景執行緒執行網路請求

方案一:AsyncTask(舊專案維護)

private class FetchTask extends AsyncTask {
    @Override
    protected void onPreExecute() {
        progressDialog = ProgressDialog.show(MainActivity.this, "載入中", "請稍候...");
    }

    @Override
    protected String doInBackground(String... urls) {
        try {
            HttpClient client = new DefaultHttpClient();
            HttpResponse response = client.execute(new HttpPost(urls[0]));
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) { return "Error: " + e.getMessage(); }
    }

    @Override
    protected void onPostExecute(String result) {
        progressDialog.dismiss();
        textView.setText(result);
    }
}

// 呼叫
new FetchTask().execute("https://google.com");

方案二:Thread + Handler(基礎寫法)

new Thread(() -> {
    try {
        String result = // ...網路請求...
        runOnUiThread(() -> textView.setText(result));
    } catch (Exception e) {
        runOnUiThread(() -> textView.setText("Error: " + e.getMessage()));
    }
}).start();

方案三:Kotlin 協程 + OkHttp(現代標準)

// build.gradle
implementation "com.squareup.okhttp3:okhttp:4.11.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"

// ViewModel 或 Activity
lifecycleScope.launch(Dispatchers.IO) {
    try {
        val response = OkHttpClient().newCall(Request.Builder().url(url).build()).execute()
        val result = response.body?.string() ?: ""
        withContext(Dispatchers.Main) { textView.text = result }
    } catch (e: Exception) {
        withContext(Dispatchers.Main) { textView.text = "Error: ${e.message}" }
    }
}

關鍵遷移提醒

  • 棄用 DefaultHttpClient:Android 6.0 移除,請改用 HttpURLConnection 或 OkHttp。
  • AsyncTask 已棄用 (API 30):新專案請直接用協程/Flow/RxJava。
  • 網路安全配置:Android 9+ 預設禁止明文 HTTP,需在 res/xml/network_security_config.xml 允許或全站 HTTPS。

核心鐵律

任何網路、資料庫、檔案 I/O、複雜運算,絕不可在主執行緒同步執行。 這是 Android 流暢體驗的基石,也是從 2.x 遷移到 4.x+ 必須重構的核心架構調整。

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