java 当我尝试记录网络响应时,OKHttp 抛出非法状态异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38641565/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
OKHttp throwing an illegal state exception when I try to log the network response
提问by Elliott Gregory Dehnbostel
I put the following interceptor on my OkHttp client:
我将以下拦截器放在我的 OkHttp 客户端上:
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
Log.d("Response", response.body().string());
return response;
}
});
However, this isn't playing nice with Retrofit 2. It seems that you can only read the stream from the response once and that might be what is causing the exception. I'm thinking retrofit is trying to parse the stream which the log already parsed. How then do I get my hands on the response? I'm currently trying to debug a very nasty and strange malformed json exception.
但是,这在 Retrofit 2 中表现不佳。似乎您只能从响应中读取一次流,这可能是导致异常的原因。我在想改造正在尝试解析日志已经解析的流。那么我如何获得响应?我目前正在尝试调试一个非常讨厌和奇怪的畸形 json 异常。
This is the exception stack trace:
这是异常堆栈跟踪:
07 - 28 10: 58: 21.575 22401 - 22529 / REDACTED E / AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
Process: REDACTED, PID: 22401
java.lang.IllegalStateException: closed
at okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java: 378)
at okio.Buffer.writeAll(Buffer.java: 956)
at okio.RealBufferedSource.readByteArray(RealBufferedSource.java: 92)
at okhttp3.ResponseBody.bytes(ResponseBody.java: 83)
at okhttp3.ResponseBody.string(ResponseBody.java: 109)
at REDACTED.ServiceGenerator.intercept(ServiceGenerator.java: 90)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java: 187)
at REDACTED.ServiceGenerator.intercept(ServiceGenerator.java: 89)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java: 187)
at REDACTED.ServiceGenerator.intercept(ServiceGenerator.java: 89)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java: 187)
at REDACTED.ServiceGenerator.intercept(ServiceGenerator.java: 89)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java: 187)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java: 160)
at okhttp3.RealCall.access0(RealCall.java: 30)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java: 127)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java: 32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java: 1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java: 587)
at java.lang.Thread.run(Thread.java: 841)
I see that there are multiple interceptors in the stack but I only ever explicitly add the one, which is the on that is throwing the exception.
我看到堆栈中有多个拦截器,但我只明确添加了一个,即抛出异常的那个。
回答by Eric Cochran
You are consuming the response body in the interceptor, so you're going to want to create a new response:
您正在拦截器中使用响应正文,因此您将要创建一个新响应:
@Override public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
ResponseBody body = response.body();
String bodyString = body.string();
MediaType contentType = body.contentType();
Log.d("Response", bodyString);
return response.newBuilder().body(ResponseBody.create(contentType, bodyString)).build();
}
You may also want to check out the logging interceptor in OkHttp's repo: https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor
您可能还想查看 OkHttp 的 repo 中的日志拦截器:https: //github.com/square/okhttp/tree/master/okhttp-logging-interceptor
回答by Eric Cochran
Do not call response body more than once, since it is read as a stream and not stored in memory.
不要多次调用响应体,因为它是作为流读取的,而不是存储在内存中。
Maybe you are calling response.body().string() more than once because response body can be huge so OkHttp doesn't store it in memory, it reads it as a stream from network when you need it.
When you read body as a string() OkHttp downloads response body and returns it to you without keeping reference to the string, it can't be downloaded twice without new request.
也许您多次调用 response.body().string() ,因为响应主体可能很大,所以 OkHttp 不会将其存储在内存中,它会在您需要时将其作为来自网络的流读取。
当您将 body 作为 string() 读取时,OkHttp 会下载响应正文并将其返回给您,而不保留对字符串的引用,如果没有新请求,则无法下载两次。
回答by Gaurav Pandit
I also got this exception due to trying to convert response body 2X.First i logged the response.body().string()& then again i passed the same to a method. Which was causing the exception. Check if the response body is converted to string more than once.
由于尝试将响应正文转换为2X,我也遇到了此异常。首先我记录了response.body().string()& 然后我再次将它传递给一个方法。这导致了异常。检查响应正文是否多次转换为字符串。
回答by Dhananjay Kumar
Response body can be huge so OkHttp doesn't store it in memory, it reads it as a stream from network when you need it.
响应主体可能很大,因此 OkHttp 不会将其存储在内存中,而是在您需要时将其作为来自网络的流读取。
When you read body as a string() OkHttp downloads response body and returns it to you without keeping reference to the string, it can't be downloaded twice without new request.
当您将 body 作为 string() 读取时,OkHttp 会下载响应正文并将其返回给您,而不保留对字符串的引用,如果没有新请求,则无法下载两次。
回答by Ivan Andreyshev
I have this error when try to upload file (image) and use Chrome DevTools (Stetho).
尝试上传文件(图像)并使用 Chrome DevTools (Stetho) 时出现此错误。
Turning off Chrome DevTools solve my problem
关闭 Chrome DevTools 解决了我的问题
回答by Aashrai Ravooru
The error is weird but the the first problem I see is that you are using OKHTTP3 and trying to add a builder to the already created client.
该错误很奇怪,但我看到的第一个问题是您正在使用 OKHTTP3 并尝试向已创建的客户端添加构建器。
The OkHttpClientis immutablenow and you will have to add the interceptors directly to the OkHttpClient.Builderby calling addInterceptormethod on the builder.
该OkHttpClient是不可变的,现在,你将不得不直接添加拦截到OkHttpClient.Builder通过调用addInterceptor方法的建设者。
For more clarity on how to do this see this Github Issue. I think this should solve your problem.
要更清楚地了解如何执行此操作,请参阅此Github 问题。我认为这应该可以解决您的问题。