J'ai un ViewPager
et trois appels au service web sont effectués lorsque le ViewPager
est chargé simultanément.
Lorsque le premier renvoie 401, l'Authenticator
est appelé et je rafraîchis le jeton à l'intérieur de l'Authenticator
, mais les 2 requêtes restantes sont déjà envoyées au serveur avec l'ancien jeton de rafraîchissement et échouent avec 498, ce qui est capturé dans l'intercepteur et l'application est déconnectée.
Ce n'est pas le comportement idéal que je m'attendrais. Je voudrais garder la 2e et la 3e requête dans la file d'attente et lorsque le jeton est rafraîchi, réessayer la requête mise en attente.
Actuellement, j'ai une variable pour indiquer si le rafraîchissement du jeton est en cours dans l'Authenticator
, dans ce cas, j'annule toutes les demandes ultérieures dans l'Interceptor
et l'utilisateur doit rafraîchir manuellement la page ou je peux déconnecter l'utilisateur et le forcer à se connecter à nouveau.
Quelle est une bonne solution ou architecture pour le problème ci-dessus en utilisant okhttp 3.x pour Android?
MODIFIER : Le problème que je veux résoudre est général et je ne souhaite pas séquencer mes appels, c'est-à-dire attendre qu'un appel se termine pour rafraîchir le jeton, puis envoyer le reste de la demande au niveau de l'activité et du fragment.
Le code a été demandé. Voici un code standard pour l'Authenticator
:
public class CustomAuthenticator implements Authenticator {
@Inject AccountManager accountManager;
@Inject @AccountType String accountType;
@Inject @AuthTokenType String authTokenType;
@Inject
public ApiAuthenticator(@ForApplication Context context) {
}
@Override
public Request authenticate(Route route, Response response) throws IOException {
// Invalider le jeton d'authentification
String accessToken = accountManager.peekAuthToken(account, authTokenType);
if (accessToken != null) {
accountManager.invalidateAuthToken(accountType, accessToken);
}
try {
// Obtenir un nouveau jeton de rafraîchissement. Cela invoque l'Authentificateur de compte personnalisé qui effectue un appel pour obtenir un nouveau jeton de rafraîchissement.
accessToken = accountManager.blockingGetAuthToken(account, authTokenType, false);
if (accessToken != null) {
Request.Builder requestBuilder = response.request().newBuilder();
// Ajouter des en-têtes avec le nouveau jeton de rafraîchissement
return requestBuilder.build();
} catch (Throwable t) {
Timber.e(t, t.getLocalizedMessage());
}
}
return null;
}
}
Quelques questions similaires à celle-ci : OkHttp and Retrofit, refresh token with concurrent requests
0 votes
Veuillez poster du code
0 votes
Pouvez-vous poster votre code d'authentification ? Merci. De plus, pourquoi obtenez-vous 498 de votre API avec votre jeton expiré ?
0 votes
@savepopulation 498 signifie Jeton invalide. Les 2 demandes qui ont été envoyées avec la première demande ont un jeton obsolète et la demande échoue avec le code d'erreur 498.
0 votes
Alors, qu'est-ce qui vous empêche de répéter la 2ème et la 3ème requête lorsque vous obtenez le jeton rafraîchi?
0 votes
@matrice Je dois mettre en file la demande échouée dans l'Intercepteur et la réessayer avec un nouveau jeton de rafraîchissement. Tout d'abord, je dois avoir un événement pour remarquer que le nouveau jeton de rafraîchissement est disponible, puis je dois recommencer toutes les demandes échouées. Je n'ai pas trouvé de moyen de le faire dans l'Intercepteur. De plus, cela ne semble pas être une bonne solution et je me demande quel est le motif commun pour rafraîchir le jeton en utilisant okhttp
0 votes
Oh compris. Je vais noter ma réponse quand j'aurai le temps, mais simplement vous pouvez créer un fil qui actualise le jeton et effectuer votre appel rétrofit synchronisé dans votre fil. Vous pouvez définir un CountDownLatch et si votre fil de rafraîchissement fonctionne, attendez le compte à rebours, sinon démarrez le fil de rafraîchissement. Enfin, lorsque vous avez actualisé le jeton, enregistrez-le et comptez votre verrouillage et laissez les autres demandes lire le jeton actualisé et procéder à la demande.
0 votes
Est-ce qu'une réponse utilisant RxJava est acceptable ?
0 votes
Lorsque vous obtenez l'erreur 498 dans l'intercepteur, pouvez-vous rappeler votre appelant avec "onError()", et il fera une nouvelle tentative? (Il aura un jeton valide cette fois)
0 votes
J'ai posé cette question parce que je pense que c'est la bonne façon de le faire : les appels parallèles, et les tentatives au niveau de l'appelant, pas au niveau de retrofit
0 votes
@sat J'ai le même problème, avez-vous trouvé une solution?
0 votes
À travers des blocs de code synchronisés, vous pouvez résoudre le problème. medium.com/bazaar-tech/…