Обобщите способ обработки ответа и ошибки для всех вызовов веб-сервисов - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь создать обобщенный подход для обработки следующего

  1. ответ от веб-сервиса
  2. для обработки ошибок HTTP и пользовательских ошибок

для этого я написал следующий код и создал обратные вызовы для обработки ответа ResponseCallback и ошибок ErrorCallback.

Для извлечения данных, связанных с питанием или любыми другими объектами, я могу использовать те же обратные вызовы.

    Request request = new Request();
    request.setAccess_token("d80fa6bd6f78cc704104d61146c599bc94b82ca225349ee68762fc6c70d2dcf0");
    request.setStart_date("2018-06-01T00:00:00");
    Flowable<Response> fitnessFlowable = new WebRequest()
            .getRemoteClient()
            .create(FitnessApi.class)
            .getFitnessData("5b238abb4d3590001d9b94a8",request.toMap());

      fitnessFlowable.subscribeOn(Schedulers.io())
            .takeUntil(response->response.getSummary().getNext()!=null)
            .doOnNext(new ResponseCallback())
            .doOnError(new ErrorCallback<Throwable>())
            .subscribe();

Ответный обратный вызов

public  class ResponseCallback<T extends Response> implements Consumer<Response> {


    @Override
    public void accept(Response response) throws Exception {
        if(response ==null || response.getFitness() == null || response.getFitness().isEmpty()) {


            new Exception("NUll response");

        }

        RxBus.getInstance().send(response.getFitness());
       Log.e("Data","accept");
        try(Realm r = Realm.getDefaultInstance()) {
            r.executeTransaction((realm) -> {
                realm.copyToRealmOrUpdate(response.getFitness());
            });
        }
    }
}

Ошибка обратного вызова

public class ErrorCallback <T extends Throwable> implements Consumer<Throwable> {

    public static final String TAG = "ErrorCallback";
    @Override
    public void accept(Throwable e) throws Exception {

        if (e instanceof HttpException) {
            ResponseBody body = ((HttpException) e).response().errorBody();
            try {
                Response response=  LoganSquare.parse(body.byteStream(),Response.class);

                if(response.getErrors() !=null)
                    if(response.getErrors().size() > 0)
                      Log.e(TAG , response.getErrors().get(0).getErrors() );

            } catch (IOException t) {
                t.printStackTrace();
            }

        } else if (e instanceof SocketTimeoutException) {

            Log.e(TAG , e.getMessage() );

        }else if (e instanceof IOException) {

            Log.e(TAG , e.getMessage() );
        }else{
            Log.e(TAG , e.getMessage() );
        }
    }
}

Две проблемы здесь я пытаюсь решить

  1. Для обработки ответа и ошибки мне нужно сделать два отдельных обратных вызова. Есть ли другой способ, где я могу обработать ответ и ошибку в обратном вызове, вместо создания двух отдельных

  2. Когда я должен избавиться от подписки в вышеприведенном коде, потому что в моем коде видно, что моя подписка торгуется.

Я ссылался на эту ссылку для разработки обобщающего подхода.

1 Ответ

0 голосов
/ 17 июля 2018

Решение вопроса № 1 -

Чтобы обработать ответ и ошибку, мне нужно сделать два отдельных обратных вызова. является Есть ли другой способ, где я могу обработать ответ и ошибку в обратном вызове вместо создания двух отдельных

В подходе «Чистая архитектура» ваш веб-сервис будет определяться как RemoteDataSource (вероятно, в соответствии с протоколом «DataSource». RemoteDataSource должен сериализовать свой результат в формате класса - если вы можете использовать Kotlin, тогда Sealed Class отличный вариант здесь (если Kotlin не вариант - :( - тогда посмотрите Enums или IntDefs). См. следующее:

/**
 * The return state from the Data Layer
 */
sealed class ServiceResult {

    data class Success(val list: List<MySerializedObject>) : ServiceResult()

    data class Error(val reason: Throwable?) : ServiceResult()
}

Это позволяет передавать одно состояние обратно со слоя данных, через слой домена (где вы можете выполнять дополнительную логику на основе результата) и, наконец, в слой просмотра, где докладчик может включить это как таковой:

  when (result) {
                    is ServiceResult.Success -> {
                        serializeToViewModel(result) // VM to the Adapter
                    }
                    is ServiceResult.Error -> result.reason?.let {
                        PartialViewState.Error(it) // Can be rendered immediately
                    } 
                }

Ваш докладчик может затем вызвать метод рендеринга для представления следующим образом:

            ... subscribeOn() etc
            .subscribe({ view?.render(it) }, { view?.render(ViewState(error = it)) })

Затем метод визуализации вашего представления может выполнять небольшую логику при переключении между отображаемыми состояниями отображения, отображаемым сообщением об ошибке и т. Д.

К вашему сведению, архитектура, которую я использую, в значительной степени опирается на MVI Ханса Дорфмана ... Я настоятельно рекомендую это.

...