[英]Wait for the request in a Retrofit2 Callback in Android Studio
I try to get better with retrofit requests and custom callbacks in my application.我尝试在我的应用程序中改进改造请求和自定义回调。 When I log in, my backend generates a token for the user.
当我登录时,我的后端会为用户生成一个令牌。 Every
X seconds/minutes
, my token becomes deprecated and I need to generate/refresh a new token when I do a new request.每
X seconds/minutes
,我的令牌就会被弃用,我需要在执行新请求时生成/刷新新令牌。
The problem I have is that when the token is deprecated, I can't generate a new one before the request.我遇到的问题是,当令牌被弃用时,我无法在请求之前生成一个新的。
In MainActivity.java在MainActivity.java 中
ApiService mApiService = RetrofitClientInstance.getRetrofitInstance().create(ApiService.class);
Call < Data > call = mApiService.getData(config.token, params); //My actual token and some custom parameters
call.enqueue(new MyCallback < Data > () {
@Override
public void onResponse(Call < Data > call, Response < Data > response) {
super.onResponse(call, response);
config.data = response.body(); //configuration class where I store the result of the request
startActivity(new Intent(this, NewActivity.class);
}
@Override
public void onFailure(Call < Data > call, Throwable t) {
super.onFailure(call, t);
}
});
In MyCallback.java在MyCallback.java 中
public class MyCallback < T > implements Callback < T > {
private String TAG = "MyCallback";
private ApiService mApiService = ConnectionsRequest.getApiService();
@Override
public void onResponse(Call < T > call, Response < T > response) {
if (new Gson().toJson(response.body()).contains("needrefreshtoken")) {
Log.i(TAG, "Generate new token");
mApiService.getRefreshToken(config.login.getRefreshToken()).enqueue(new Callback() {
@Override
public void onResponse(Call < RefreshToken > call, Response < RefreshToken > response) {
config.token = response.body().getNewToken();
Log.i(TAG, "New token generated");
}
@Override
public void onFailure(Call < RefreshToken > call, Throwable t) {
super.onFailure(call, t);
}
});
}
}
@Override
public void onFailure(Call < T > call, Throwable t) {
Log.e(TAG, t.toString());
}
}
It seems like I do the main request before (or during) the refresh token request.似乎我在刷新令牌请求之前(或期间)执行了主要请求。
How can I improve my code to do this step by step (refresh the token then do the main request)?如何改进我的代码以逐步执行此操作(刷新令牌然后执行主要请求)?
Thanks for your help.谢谢你的帮助。
We have remember below things when using dynamic header integration (tokens).在使用动态标头集成(令牌)时,我们记住了以下内容。
so we need the callback for detect token expired when calling api, so we use Authendicator
, It's will trigger when our api getting 401(add authenticator class if you have send token with api).所以我们在调用api时需要检测token过期的回调,所以我们使用
Authendicator
,当我们的api得到401时它会触发(如果你Authendicator
api发送令牌,请添加authenticator类)。
If you getting 401, call your refresh api and then again recall your existing api with new token.如果您收到 401,请调用您的刷新 api,然后再次使用新令牌调用您现有的 api。
Authendicator:验证者:
class TokenAuthenticator implements Authenticator {
@Nullable
@Override
public Request authenticate(@NonNull Route route, @NonNull Response response) throws IOException {
//call your refersh token api
//returned new request with updated header
return response.request().newBuilder()
.header("AUTHORIZATION", "new token from refresh token api")
.build();
}
}
Then add Authendicator to your okhttp client然后将 Authendicator 添加到您的 okhttp 客户端
.authenticator(new TokenAuthenticator())
So i have found a custom solution that works.所以我找到了一个有效的自定义解决方案。 I hope I will help people with that.
我希望我能帮助人们解决这个问题。 I wanted to simplify as much as I can the requests, so this is how looks an http request :
我想尽可能地简化请求,所以这是一个 http 请求的样子:
MainActivity.java主活动.java
@OnClick(R.id.button)
@Optional
void onClickButton()
{
JsonObject params = new JsonObject();
params.addProperty("key", "value");
Call < MyModel > call = myApiService.postCustomRequest(params);
RetrofitCallback.enqueue(call, new Callback < MyModel >() {
@Override
public void onResponse(@NonNull Call<NewIncidentData> call, @NonNull Response<NewIncidentData> response) {
//Do you stuff here, no need to add custom request code
}
@Override
public void onFailure(@NonNull Call<NewIncidentData> call, @NonNull Throwable t) {
//Same here
}
});
}
RetrofitCallback.java RetrofitCallback.java
public class RetrofitCallback {
public static <T> void enqueue(Call<T> call, final Callback<T> callback) {
Log.i(TAG, "HTTP Request : " + call.request().url());
call.enqueue(new CustomCallback<T>(call) {
@Override
public void onResponse(Call<T> call, Response<T> response) {
super.onResponse(call, response);
if(call.isCanceled())
return;
callback.onResponse(call, response);
}
@Override
public void onFailure(Call<T> call, Throwable t) {
super.onFailure(call, t);
callback.onFailure(call, t);
}
});
}
}
CustomCallback.java自定义回调函数
public class CustomCallback<T> implements Callback<T> {
private String TAG = "CustomCallback";
private ApiService mApiService = ConnectionsRequest.getApiService();
private Config config = Config.getInstance();
public CustomCallback(Call<T> call) {
this.call = call;
}
@Override
public void onResponse(Call<T> main_call, Response<T> response) {
//Check if the token is still valid
if (new Gson().toJson(response.body()).contains("needrefreshtoken")) {
Log.i(TAG, "Generate new token");
main_call.cancel();
RetrofitCallback.enqueue(mApiService.getToken(config.refreshtoken()), new Callback<TokenModel>() {
@Override
public void onResponse(@NonNull Call<TokenModel> call, @NonNull Response<TokenModel> response) {
config.token = response.body().getToken();
Log.i(TAG, "New token generated and saved");
retryMainRequest();
}
@Override
public void onFailure( @NonNull Call<TokenModel> call, @NonNull Throwable t) {
}
});
}
}
@Override
public void onFailure(Call<T> call, Throwable t) {
Log.e(TAG, t.toString());
}
private void retryMainRequest() {
Log.i(TAG, "Retry request");
call.clone().enqueue(this);
}
}
EDIT : I forget some code :编辑:我忘记了一些代码:
RetrofitClientInstance.java改造客户端实例.java
public class RetrofitClientInstance {
private static Retrofit retrofit;
private static final String BASE_URL = "myurl.com";
public static Retrofit getRetrofitInstance() {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addNetworkInterceptor(new AuthInterceptor()); // I added that
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(httpClient.build())
.build();
return retrofit;
}
}
AuthInterceptor.java AuthInterceptor.java
public class AuthInterceptor implements Interceptor {
Config config = Config.getInstance();
@Override
public Response intercept(Chain chain) throws IOException
{
Request request = chain.request();
request = request.newBuilder()
.addHeader("X-AUTH-TOKEN", config.token).build();
return chain.proceed(request);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.