2016-11-23 7 views
0

У меня есть следующий класс:Вызов другой дооснащения вызов по эмиссии Subject

public class SessionStore { 
    Subject<Session, Session> subject; 

    public SessionStore() { 
     subject = new SerializedSubject<>(BehaviorSubject.create(new Session()); 
    } 

    public void set(Session session) { 
     subject.onNext(session); 
    } 

    public Observable<UserSession> observe() { 
     return subject.distinctUntilChanged(); 
    } 
} 

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

private Subscription init() { 
    return sessionStore 
      .observe() 
      .flatMap(new Func1<Session, Observable<Object>>() { 
       @Override 
       public Observable<Object> call(Session session) { 
        return (session.isValid() 
         ? retrofitService.getThingForValid() 
         : retrofitService.getThingForInalid()) 
         .subscribeOn(Schedulers.io()); 
       } 
      }) 
      .subscribe(...); 
} 

Теперь у меня есть Okhttp запрос перехватчика, в котором я установил экземпляр сеанса из действительного в недействительный, когда ответ сети не является кодом 200.

Это то, что происходит:

  1. На начальной подписке на сессию МАГАЗИН getThingForValid() выполняется, и выходит из строя.
  2. OkHttp перехватывает неудачу и устанавливает новый сеанс.
  3. Магазин сеансов испускает новую, теперь недействительную сессию.
  4. Новая эмиссия выполняет метод getThingForInvalid().

Важно знать, что это выполнение происходит в середине предыдущего запроса на доработку. Это связано с тем, что OkHttp-клиент завершен с помощью Retrofit, и все перехватчики выполняются до возврата Retrofit.

Имея это в виду, вы понимаете, что второй вызов выполняется и обрабатывается с помощью «Дооснащения» уже, пока первый еще не закончен.

  1. По завершении первого вызова он выдает исключение HttpException, потому что ответ был не 200 кода.
  2. xception убивает поток rx, а вместе с ним второй вызов.

Я попытался проигнорировать это исключение в потоке, но второй вызов в любом случае отменен с помощью Retrofit.

У вас есть идеи, как сделать мою концепцию работать, пожалуйста?

+0

Вы что-то пробовали в духе '.onErrorResumeNext (err -> Observable.empty())'? –

+0

Да, у него такой же выход. Это должно иметь какое-то отношение к внутренним частям Retrofit, а не к RxJava. – bakua

+0

Можете ли вы объяснить абстрактно, что вы пытаетесь достичь и какова ваша первоначальная проблема? –

ответ

0

если вы получите код ответа 401 в случае истечения срока действия маркера: вам нужно добавить Authenticator, чтобы OkHttpClient.Builder

builder.authenticator(new Authenticator() { 
      @Override 
      public Request authenticate(Route route, Response response) throws IOException { 
       final LoginResponse newLoginResponse = refreshTokenClient.refreshToken(); 
       //save new token locally, if needed 
       return response 
         .request() 
         .newBuilder() 
         .removeHeader("Api-Auth-Token") // removing old header 
         .addHeader("Api-Auth-Token", newLoginResponse.getAuthToken()) 
         .build(); 
      } 
     }); 

где

public interface RefreshTokenService { 

    @PUT("/api/v1/tokens") 
    LoginResponse refreshToken(); 

} 

Но обратите внимание: это Authenticator будет запускаться каждый раз когда код ответа 401.

+0

Да, но я не могу обновить токен, мне нужно повторно выполнить логику бизнес-активности, которую я делаю в потоке. В любом случае я разрешил свою проблему с использованием другой плоской карты. Я отправлю решение позже. Благодаря :) – bakua