java.lang.IllegalStateException из-за кода onResponse в okhttp асинхронном HTTP-запросе POST - PullRequest
0 голосов
/ 25 октября 2018

Я написал код здесь:

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;
            }

}

Когда я запускаю это, удивительно, я получаю 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) в okhttp3.ternal(Util.java:431) на okhttp3.ResponseBody.string (ResponseBody.java:174) 10-24 05: 16: 38.308 6639-6659 / com.example.android.persistence W / System.err:
на андроиде.support.v17.leanback.supportleanbackshowcase.app.wizard.: 32) в java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1133) в java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:607) в java.lang.Thread.hread.java:761)

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Вы используете 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();
        }
    }
}

Или вы можете скопировать 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);
}

Но будьте осторожны, чтобы правильно использовать bufferSize, чтобы предотвратить OutOfMemoryError

Ps вам не нужно записывать строку в Logcat.Есть несколько более эффективных способов отладки клиента OkHttp, таких как

0 голосов
/ 25 октября 2018

Тело из Retrofit Ответ может быть получен только один раз, очищается после прочтения, в вашем случае во второй раз регистрируется на консоли.

Из документации:

Aоднократный поток от исходного сервера к клиентскому приложению с необработанными байтами тела ответа.

Подробнее о официальной документации .

Вам следуетпродолжайте использовать сохраненную переменную myResponse.

...