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

Android 主線程網絡請求崩潰:NetworkOnMainThreadException 解決 (AsyncTask/協程)

     編輯:程式設計綜合問答

錯誤現象

在 onCreate 中直接執行 HttpURLConnection 獲取 JSON,Android 4.0+ 拋出 NetworkOnMainThreadException (調試斷在 getResponseCode())。

原因

Android 3.0+ (Honeycomb) **嚴禁主線程執行網絡 I/O**,防止 ANR。

解決方案

方案一:AsyncTask (舊 API,API 30 棄用但仍可用)

private class FetchJsonTask extends AsyncTask {
    @Override
    protected List<Map<String,String>> doInBackground(String... urls) {
        // 此處執行網絡請求、解析 JSON,返回結果
        return getJSONObject(urls[0]);
    }
    @Override
    protected void onPostExecute(List<Map<String,String>> result) {
        // UI 線程更新界面
        adapter.setData(result);
    }
}
// 調用
new FetchJsonTask().execute("https://m.lalas.cn/help/all_1.html?format=json&size=5");

方案二:Kotlin 協程 (現代首選)

// build.gradle: implementation "org.jetbrains.kotlinx:kotlin-coroutines-android:1.6.+"
lifecycleScope.launch(Dispatchers.IO) {
    val result = getJSONObject(url) // 懸掛函數或 runBlocking
    withContext(Dispatchers.Main) {
        adapter.submitList(result)
    }
}

方案三:RxJava / Retrofit + OkHttp (成熟框架)

// Retrofit 定義接口
interface ApiService {
    @GET("help/all_1.html")
    fun getHelp(@Query("format") String format, @Query("size") Int size): Observable
}

// 使用
apiService.getHelp("json", 5)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ result -> /* 更新 UI */ }, { err -> /* 錯誤處理 */ })

代碼修正要點

  • 將網絡請求移出主線程(doInBackground / Dispatchers.IO / subscribeOn(Schedulers.io()))。
  • 解析 JSON 邏輯同步移入後台。
  • UI 更新回主線程(onPostExecute / withContext(Main) / observeOn(Main))。
  • 權限:<uses-permission android:name="android.permission.INTERNET"/> 已添加。

總結

**主線程不能做網絡請求**,使用 AsyncTask/協程/RxJava 將耗時操作移至後台線程,結果回主線程更新 UI。

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