我正在开发使用我的 API 的 Android 应用程序。我想在应用程序中以测试模式使用 API,但是当我尝试调用不使用 https 的请求 API 时,会发生 NetworkOnMainThreadError
我使用 OkHTTP
请求示例:
val baseURL = "http://192.168.1.100:5555/api"
val authToken = "TOKEN"
val client = OkHttpClient.Builder().cache(
Cache(context.cacheDir, 20 * 1024 * 1024)
).build()
CoroutineScope(Dispatchers.Main).launch {
val urlBuilder = baseURL.toHttpUrl()
.newBuilder()
.addPathSegments("compositions/search")
response = withContext(Dispatchers.IO) {
client.newCall(
Request.Builder()
.get()
.url(urlBuilder.build())
.addHeader("Authorization", "bearer $authToken")
.build()
).execute()
}
val body = response.body!!.string()
}
错误示例:
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1605)
at java.net.SocketInputStream.read(SocketInputStream.java:175)
at java.net.SocketInputStream.read(SocketInputStream.java:144)
at okio.InputStreamSource.read(JvmOkio.kt:94)
at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:125)
at okio.RealBufferedSource.read(RealBufferedSource.kt:189)
at okhttp3.internal.http1.Http1ExchangeCodec$AbstractSource.read(Http1ExchangeCodec.kt:331)
at okhttp3.internal.http1.Http1ExchangeCodec$FixedLengthSource.read(Http1ExchangeCodec.kt:368)
at okhttp3.internal.connection.Exchange$ResponseBodySource.read(Exchange.kt:276)
at okio.RealBufferedSource.select(RealBufferedSource.kt:229)
at okhttp3.internal.Util.readBomAsCharset(Util.kt:265)
at okhttp3.ResponseBody.string(ResponseBody.kt:187)
at com.vhu.mitsu.api.MitsuAPI.getError(MitsuAPI.kt:145)
at com.vhu.mitsu.api.MitsuAPI.prolongAuth(MitsuAPI.kt:598)
at com.vhu.mitsu.api.MitsuAPI$prolongAuth$1.invokeSuspend(Unknown Source:14)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:8057)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011)
Suppressed: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1605)
at java.net.SocketInputStream.read(SocketInputStream.java:175)
at java.net.SocketInputStream.read(SocketInputStream.java:144)
at okio.InputStreamSource.read(JvmOkio.kt:94)
at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:125)
at okio.RealBufferedSource.read(RealBufferedSource.kt:189)
at okhttp3.internal.http1.Http1ExchangeCodec$AbstractSource.read(Http1ExchangeCodec.kt:331)
at okhttp3.internal.http1.Http1ExchangeCodec$FixedLengthSource.read(Http1ExchangeCodec.kt:368)
at okhttp3.internal.Util.skipAll(Util.kt:344)
at okhttp3.internal.Util.discard(Util.kt:365)
at okhttp3.internal.http1.Http1ExchangeCodec$FixedLengthSource.close(Http1ExchangeCodec.kt:387)
at okio.ForwardingSource.close(ForwardingSource.kt:34)
at okhttp3.internal.connection.Exchange$ResponseBodySource.close(Exchange.kt:309)
at okio.RealBufferedSource.close(RealBufferedSource.kt:477)
at kotlin.io.CloseableKt.closeFinally(Closeable.kt:59)
at okhttp3.ResponseBody.string(ResponseBody.kt:186)
... 12 more
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@ecd807f, Dispatchers.Main]
我尝试将所有使用服务器响应的代码包装在 withContext(Dispatchers.IO) 中。但它也会引发同样的错误
移动:
val body = response.body!!.string()
位于
IO
协程内部:
response = withContext(Dispatchers.IO) {
client.newCall(
Request.Builder()
.get()
.url(urlBuilder.build())
.addHeader("Authorization", "bearer $authToken")
.build()
).execute()
val body = response.body!!.string()
}