Как написать перехватчик для потока данных в OkHttp?

Или думаешь, что перехватчик для этого сценария применим?

Наше приложение использует OkHttp для загрузки файлов (новая версия приложения, ежедневные базы данных и т. Д.)

Иногда происходит сбой сервера только во время потоковой передачи байтов приложения (кстати, проблема в том, что recvfrom не удалось: ECONNRESET)

Так что, чтобы исправить это дело, я просто хотел написать перехватчик попыток OkHttp. Но, похоже, это подходит для операций, которые не являются потоковыми.

Есть ли решение (например, перехватчик) для обработки этого случая?


Чтобы сделать экспозицию более понятной

0%==============================100% (только начал потоковую передачу)

0%============================== 100% (10% выполнено)

0%============================== 100% (выполнено20%)

0%============================== 100% (ECONNRESET - сброс соединения по пиру)

В этот момент потоковая передача останавливается. Единственное, чего я желаю от OkHttp, это распознать эту ситуацию, а затем запустить поток с нуля (не с 20%).


Связанный код здесь, обратите внимание на комментарии

 Call call = client.newCall(new Request.Builder().url(url).get().build());
 Response response = call.execute();
 // PROBLEM DOES NOT OCCUR THERE
 // PROBLEM DOES NOT OCCUR THERE
 // PROBLEM DOES NOT OCCUR THERE
 if (response.code() == 200 || response.code() == 201) {
     InputStream inputStream = null;
     try {
         long downloaded = 0;
         byte[] buff = new byte[1024 * 4];
         inputStream = response.body().byteStream();
         long target = response.body().contentLength();
         while (true) {
             // EXCEPTION OCCURS THERE
             // EXCEPTION OCCURS THERE
             // EXCEPTION OCCURS THERE
             int read = inputStream.read(buff);
             if (read == -1) {
                 break;
             }
             downloaded += read;
         }
         ...
     } catch (IOException e) {
         // EXCEPTION SAYS 
         // ECONNRESET - Connection reset by peer
         ...
     }
}

3 ответа

Вы можете написать собственный перехватчик, как показано ниже:

OkHttp имеет перехватчики. Вам нужен пользовательский перехватчик, как показано ниже:

public class CustomResponseInterceptor implements Interceptor {

    private final String TAG = getClass().getSimpleName();

    @Override
    public Response intercept(Object object) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);
        if (response.code() != 200//Your error code here,) {
           //Cancel your Request here
            return something;
        }
        Log.d(TAG, "INTERCEPTED:$ " response.toString());
        return response;
    }

Показанный код извлечен из этой средней статьи о перехватчиках.
Вы также можете посмотреть на эту библиотеку, которая реализует перехватчики Retry, но вы можете изменить ее для своего использования.

Когда ECONNRESET - Connection reset by peer происходит, почему бы вам не отменить текущий вызов в блоке перехвата и начать новый сетевой вызов для того же файла

catch (IOException e) {
         // EXCEPTION SAYS 
         // ECONNRESET - Connection reset by peer
         ...
         call.cancel();//something like this
         startDownloadingFromScratch();//new network request to start from scratch  
     }

Попробуй это.

OkHttpClient client = new OkHttpClient();
    client.setConnectTimeout(CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
    client.setReadTimeout(READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
    client.interceptors().add(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            // try the request
            Response response = chain.proceed(request);

            int tryCount = 0;
            while (!response.isSuccessful() && tryCount < 3) {

                Log.d("intercept", "Request is not successful - " + tryCount);

                tryCount++;

                // retry the request
                response = chain.proceed(request);
            }

            // otherwise just pass the original response on
            return response;
        }
    });

установите этот клиент в качестве вашего модифицированного клиента.

new Retrofit.Builder()
    ...other codes
    .client(client)
    ...other codes
    .build();

Удачи.

Другие вопросы по тегам