简体   繁体   中英

Transform Observable onError and emit an item

In my Android App I have a generated (Swagger) ApiClient which gets initialized with a Token to identify the User.

This Token (which comes from the Server) can expire.

I get Observable´s with Data from my WebService via myApiClient.myServiceMethod(params)

When I get 401 from the Server it means my Token is expired and I have to initialize myApiClient again (to get it with an unexpired Token).

How myApiClient is initialized. It is returned by getMyApiClient()

 //getOkHttpClientWithToken() first issues another Server call to get an
 //unexpired Token and then returns an OkHttpClient with that Token set.

 myApiClient = new ApiClient()
              .getAdapterBuilder()
              .baseUrl(url)
              .client(getOkHttpClientWithToken())
              .build()
              .create(MyApiClient.class);

I get the Observable from myApiClient calls

Observable<Result> getResultObservable(Type param1, Type param2) {
    return Observable.just(getMyApiClient())
                     .flatMap(myApiClient ->
                        myApiClient.getResult(param1, param2).cache()
                      );
}

What I tried is

//How to recreate myApiClient and Retry call on new myApiClient when an Error occurs
getResultObservable(param1, param2)
  .take(1)
  .subscribe(result -> {
     doSomethingWithResult();
   }
});

Works but is done on every error, not just 401 and may never end

I need something like

getResultObservable(param1, param2)
  .take(1)
  .subscribe(result -> {
     doSomethingWithResult();
   }, e -> {
     if(e.getMessage.equals("HTTP 401")) {
         "Transform this Observable to getResultObservable with new myApiClient and emit Result in onNext"
     } else {
       "Other error inform User and stop."
     }      
   }
});

You may use Observable#onErrorResumeNext to provide an fallback-observable. You can check the exception for typ and return a fallback-observable, if given condition is met or just wrap the exception with Observable#error.

Please have a look at the test, how #onErrorResumNext is used, to provide an fallback-observable, when some exception happens.

  @Test
  void nameX() {
    Observable<String> stringObservable = get();

    Observable<String> fallback$ =
        stringObservable
            .doOnError(s -> System.out.println("fail -> " + s.getMessage()))
            .onErrorResumeNext(
                throwable -> {
                  if (throwable instanceof MyException) {
                    return fallBack().doOnNext(s -> System.out.println("use fallback value " + s));
                  } else {
                    return Observable.error(throwable);
                  }
                });

    fallback$
        .test()
        .assertNotComplete()
        .assertValueCount(1)
        .assertValueAt(0, s -> "Wurst".equals(s));
  }

  private Observable<String> get() {
    return Observable.error(new MyException("Fail"));
  }

  private Observable<String> fallBack() {
    return Observable.just("Wurst").mergeWith(Observable.never());
  }

  private static final class MyException extends Exception {
    MyException(String message) {
      super(message);
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM