Kotlin OkHTTP android.os.NetworkOnMainThreadException

Kotlin OkHTTP android.os.NetworkOnMainThreadException

提问人:Legendary 提问时间:1/4/2022 最后编辑:SergioLegendary 更新时间:10/26/2022 访问量:1988

问:

我正在使用 kotlin 发送 http 请求并收到此错误

错误:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx/xxx.android.ui.xxx}: android.os.NetworkOnMainThreadException

附加信息:GET 请求需要首先工作。因为该过程根据 URL 的响应进行。

我的代码:

override fun onCreate(savedInstanceState: Bundle?) {

    setTheme(R.style.AppTheme_MainActivity)
    super.onCreate(savedInstanceState)

    val request = Request.Builder()
        .url("https://publicobject.com/helloworld.txt")
        .build()

    client.newCall(request).execute().use { response ->
        if (!response.isSuccessful) throw IOException("Unexpected code $response")

    
    }

  
}
人造人 科特林 确定http kotlin-协程 NetworkOnMainThread

评论

0赞 darshan 1/4/2022
使用其他线程或使用协程。
0赞 Legendary 1/4/2022
我对 kotlin 很陌生,我该怎么做?
0赞 darshan 1/4/2022
这应该给你一个想法:developer.android.com/kotlin/coroutines

答:

3赞 Sergio 1/4/2022 #1

Android 主要组件(如 等)在主线程中运行。您无法在主线程中发出网络请求(或其他可能长时间运行的操作)。您需要在 background(worker) 线程中安排它。通过使用方法,您可以同步发送请求。即在主线程中。 您可以使用方法异步发送请求:ActivitiesBroadcastReceiverCall.execute()Call.enqueue()

client.newCall(request).enqueue(object : Callback<Response> {
    override fun onResponse(call: Call<Response>, response: Response<Response>
    ) {
        // handle response
    }

    override fun onFailure(call: Call<ApiResponse>, t: Throwable) {
       // handle error
    }

})

还有另一种使用 Kotlin 协程发出和处理请求的方法:

// suspendCoroutine - suspends a coroutine until request is executed
suspend fun makeRequest(): String = suspendCoroutine { continuation ->
    client.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            continuation.resumeWithException(e) // resume calling coroutine
            e.printStackTrace()
        }

        override fun onResponse(call: Call, response: Response) {
            response.use {
                continuation.resume(response.body!!.string()) // resume calling coroutine
            }
        }
    })
}

override fun onCreate(savedInstanceState: Bundle?) {

    // ...
    
    lifecycle.coroutineScope.launch { // launching a coroutine
        val result = makeRequest()
        // do something with result
        // save to Preferences
        getPreferences(MODE_PRIVATE).edit().putString("val001", result).apply(); //save prefences
        println("Request complete")
    }
  
}