2016-06-17 3 views
0

Мне было интересно узнать токен аутентификации с помощью Retrofit/RxJava. Я пересматривал свой код для использования DataManager, так что активность вызывает метод в презентаторе, ведущий подписывается на datamanager.getTrips, который затем отвечает за вызов api.DoOnCompleted допустимый способ обработки аутентификации маркера?

Я хочу убедиться, что мой accesstoken действителен, и если он не сгенерирует его первым, а затем выполнит задачу. Будет ли DoOnCompleted хорошим способом достижения этого или есть лучший способ?

/*In DataManager, service is the REST Interface*/ 
public Observable<VtTripResponseModel> getTrips(final String start, final String end, final String time, final String date){ 
     if(accessToken.isValid()){ 
      return service.getTrip(accessToken.getAccessString(),start,end,time,date,JSON_PARAM); 
     } 
     else{ 
      generateAccessToken().doOnCompleted(new Action0() { 
       @Override 
       public void call() { 
        getTrips(start, end, time, date); 
       } 
      }); 
     } 

/*What do I return here? Since this will not be reached*/ 
    } 
+0

Я бы просто использовал 'flatMap'. –

+0

Не специально связан с RxJava, но okHttp предоставляет перехватчик Authenticator для обработки ошибок Auth - https: // github.com/square/okhttp/wiki/Рецепты # обработка-аутентификация – Jahnold

ответ

1

Благодарим вас за ввод. Тем временем я улетаю и нашел аналогичный, но сформулировал по-другому сообщение: Retrofit with RxJava, на котором был ответ.

Мой код теперь выглядит следующим образом:

/*In DataManager*/ 
public Observable<VtTripResponseModel> getTrips(String start, String end, String time, String date){ 
      return service.getTrip(accessToken.getAccessString(),start,end,time,date,JSON_PARAM); 
    } 

public Observable<VtResponseModel> getLocationByInput(String input){ 
     return service.getLocationByInput(accessToken.getAccessString(),input,JSON_PARAM); 
    } 

/*SF 26201420*/ 
    public <T> Func1<Throwable,? extends Observable<? extends T>> refreshTokenAndRetry(final Observable<T> toBeResumed) { 
     return new Func1<Throwable, Observable<? extends T>>() { 
      @Override 
      public Observable<? extends T> call(Throwable throwable) { 
       // Here check if the error thrown really is a 401 
       if (isHttp401(throwable)) { 
        return service.getAccessToken(CREDENTIALS, DEVICE).flatMap(new Func1<AccessToken, Observable<? extends T>>() { 
         @Override 
         public Observable<? extends T> call(AccessToken token) { 
          accessToken = token; 
          return toBeResumed; 
         } 
        }); 
       } 
       // re-throw this error because it's not recoverable from here 
       return Observable.error(throwable); 
      } 
     }; 
    } 

И метод в моем предъявитель теперь выглядит

public void loadRepositories(String search){ 
    subscription = manager.getLocationByInput(search) 
       .onErrorResumeNext(manager.refreshTokenAndRetry(Observable.defer(() -> manager.getLocationByInput(search)))) 
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribeOn(application.defaultSubscribeScheduler()) 
        .subscribe(new Subscriber<VtResponseModel>() {... etc} 

Теперь, когда первый вызов выполняется после запуска программы, она будет генерировать маркер доступа так как я получаю 401. Затем этот accesstoken хранится в менеджере и повторно используется до появления нового 401 (после того, как он истек).

4

Чтобы уточнить @ david.mihola «s answear вы могли бы сделать это следующим образом:

Observable.just(accessToken.isValid()) 
    .flatMap(valid -> { 
     if(valid){ 
      return Observable.just(accessToken); 
     } else { 
      return generateAccessToken(); 
     }) 
    .flatMap(token -> service.getTrip(token.getAccessString(),start,end,time,date,JSON_PARAM)) 

Так что первый flatMap генерирует маркер, если он не является действительным, и если это так, то просто (это предполагает, что generateToken() возвращает Observable<AccessToken>). Вторая flatMap - это то, что вы хотели сделать.

+0

Спасибо, я не мог полностью обернуть голову тем, как плоская карта работала после прочтения об этом – buddhabath

+0

Путь 'if valid' должен возвращать' Observable.just (accessToken) ' –

+0

Действительно, поскольку это не карта, спасибо, что поймали это. – MatBos

2

И дать некоторый контекст @ MatBos-х разработки на мой комментарий, особенно в отношении вашего вопроса

Что я вернусь сюда? Так как это не будет достигнуто

Он чувствовал себя довольно поучительный для меня, когда я понял, что Observable (или, по крайней мере, один холодной, как тот, о котором мы говорим здесь, и тот, который @MatBos описанный в его ответе) является, по существу, описанием будущих вычислений.

Возвращаясь к Observable просто означает, что вы возвращаете сине-печати для того, что должно произойти, если и когда кто-то (я. Е. Код, который называется ваш метод getTrips) на самом деле subscribe с до этого Observable. Конечно, Observableтакже асинхронный поток событий, но я думаю, что мое описание здесь также верно.

Итак, что вы возвращаете? Описание, которое говорит:

If someone subscribes 
    1. First check if we have valid access token 
    2. a) If we do, just forward the access token for later use 
    b) If we don't, generate a new one access token and forward that 
    3. Take whatever access token you get - it is now guaranteed to be valid and use to retrieve the trips. 
    4. Forward them to the subscriber when they are ready. 

И это описание точно Observable, описанной @MatBos.

+1

Благодарим вас за понимание, это сделало его более понятным – buddhabath

Смежные вопросы