【问题标题】:Kotlin OkHTTP android.os.NetworkOnMainThreadExceptionKotlin OkHTTP android.os.NetworkOnMainThreadException
【发布时间】:2022-01-03 19:13:34
【问题描述】:

我正在使用 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")

    
    }

  
}

【问题讨论】:

标签: android kotlin okhttp


【解决方案1】:

Android 主要组件,如ActivitiesBroadcastReceiver 等,都在主线程中运行。您不能在 主线程 中发出网络请求(或其他可能长时间运行的操作)。您需要在后台(工作者)线程中安排它。通过使用Call.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 Coroutines

// 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")
    }
  
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 2013-04-24
    • 2018-06-15
    • 2012-03-13
    • 1970-01-01
    相关资源
    最近更新 更多