java.lang.IllegalStateException 由于 okhttp 异步 HTTP POST 请求中的 onResponse 代码

Sal*_*leh 3 android okhttp leanback retrofit2

我在这里写了一段代码:

public class Wizard1 extends GuidedStepFragment implements Callback {

    private boolean sendPhoneNumber(String userPhoneNumber) {

        OkHttpClient client = new OkHttpClient();

        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("request_magic_code", Urls.REQUEST_MAGIC_CODE)
                .build();

        Request request = new Request.Builder()
                .url(Urls.HOST + Urls.SEND_PHONE_NUMBER)
                .post(requestBody)
                .build();

        client.newCall(request).enqueue(this);
        return success;
    }

    @Override
    public void onFailure(@NonNull Call call, @NonNull IOException e) {
        e.printStackTrace();
    }

    @Override
    public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
        ResponseBody myResponse = response.body();
        Log.d("SS", response.body().string());

    Log.d("SS", response.body().string());

        if (myResponse != null) {
            success = true;
            }

}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,令人惊讶的是我得到了 java.lang.IllegalStateException。更令人惊讶的是,如果我删除第二个 Log.d 行,则不会发生异常!

发生了什么?为什么在 onResponse 中添加虚拟行会导致此错误?

这是错误的完整日志:

10-24 05:16:38.307 6639-6659/com.example.android.persistence W/System.err: java.lang.IllegalStateException: 在 okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:398) 关闭在 okio.RealBufferedSource。 rangeEquals(RealBufferedSource.java:392) at okhttp3.internal.Util.bomAwareCharset(Util.java:431) at okhttp3.ResponseBody.string(ResponseBody.java:174) 10-24 05:16:38.308 6639-6659/com。 example.android.persistence W/System.err:
在 android.support.v17.leanback.supportleanbackshowcase.app.wizard.WizardGetPhoneNumber.onResponse(WizardGetPhoneNumber.java:244) 在 okhttp3.RealCall$AsyncCall.execute(RealCall.java:141) 在 okhttp3.internal.NamedRunnable.run(NamedRunnable.run(NamedRunnable.run) .java:32) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 在 java.lang.Thread.run(线程.java:761)

Iev*_*nko 11

您正在使用response.body().string()两次

来自 OkHttp 3文档响应主体只能使用一次。

您可以创建局部变量并使用它

@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
    ResponseBody body = response.body();
    if(body != null) {
        try {
            //Use it anytime you want
            String responseString = body.string();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

或者你可以复制 ResponseBody

@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
    ResponseBody body = response.body();
    //Warning: this method loads the requested bytes into memory. Most
    // applications should set a modest limit on {@code byteCount}, such as 1 MiB.
    int bufferSize = 1024 * 1024;
    ResponseBody copy = response.peekBody(bufferSize);
}
Run Code Online (Sandbox Code Playgroud)

但要注意bufferSize正确使用,防止OutOfMemoryError

Ps 您不需要将字符串记录到 Logcat。有几种更有效的方法来调试 OkHttp 客户端,例如