2017-01-24 3 views
3

私は、OAuth2を使用して認証し、Retrofitを使用してRESTfulサービスからデータを取得するアプリを持っています。今、私はトークンの検索とリフレッシュを実行している。トークンは、その(スケジューラは省略)のようにリフレッシュされますRxJava:複数のリクエストが同時に送信されたときにトークンをリフレッシュする方法はありますか?

// Each Retrofit call observable is "wrapper" using this method 
protected <T> Observable<T> wrap(@NonNull final Observable<T> page) { 
    return authenticate() 
     .concatMap(token -> page) 
     .onErrorResumeNext(throwable -> { 
      Log.w(TAG, "wrap: ErrorResumeNext", throwable); 
      return refreshAccessToken() 
       .flatMap(accessToken -> page); 
     })); 
} 

// Retrieves the access token if necessary 
Observable<AccessToken> authenticate() { 
    // Already have token 
    if(accessToken != null) return Observable.just(accessToken); 
    // No token yet, fetch it 
    return api.getAccessToken(...); 
} 

// Refreshes the token 
Observable<AccessToken> refreshAccessToken() { 
    return api.refreshToken(...); 
} 

これは動作しますが、いくつかのケースでは、複数の要求を一度に送信され、彼らは両方のさわやかなプロセスを起動する - 基本的に私のアプリは、多くのトークンをリフレッシュして終わります現時点ではリクエストがあった時間があります。

質問:トークンをリフレッシュする必要がある場合、トークンをリフレッシュする必要がある進行中のリクエストの数にかかわらず、トークンをリフレッシュする必要がある場合は、最初のリクエストが正常に呼び出されて新しいトークンを取得するまで、何らかの形で他のリクエストを「待機」することはできますか?

答えて

2

トークンをリフレッシュし、認証に失敗したすべての要求に対してそのインスタンスへのアクセスを提供するために、ホット・オブザーバブルを使用してこの動作を実現しました。

share演算子を使用して、トークンを最新のものに更新するための基本的なコールド・オブザーバブルを有効にして、他のすべてのサブスクライバがその結果を共有します。要求が戻ってくると、オブザーバーを待っているすべての人は通知を受け取り、その瞬間に(演算子チェーンでのコールバックに直ちに来てdoOnUnsubscribeのコールバックに入る)、更新可能なインスタンスを破棄して次のサブスクライバが新しいインスタンスを作成します。このすべては、シングルトンパターンで簡単に実現できます。シングルトンパターンでは、リフレッシュしているオブザーバブルをシングルトンラッパークラスにラップし、getInstance()で尋ねます。要求がない場合 - インスタンスはnull - getInstanceは新しいインスタンスを作成する必要があります。

あなたが世話をする必要があるものがあります。たとえば、トークンをすべて更新して無効にするときにエラーが発生しますが、これが基本です。

これ以上詳しく説明する時間はあまりありませんが、あなた自身でこれを実装する際に問題が発生した場合は、コメントを残して、明日までにいくつかのコード例を投稿します。彼らは文脈なしではあまり意味がありません。

+0

これはトリックを行うようです!私はこれをある時点で持っていましたが、それは当時は機能しませんでした。おそらく何か別のものがあったでしょう。 – manabreak

+0

このトピックのサンプルコードを書くことができますか? –

関連する問題