Ожидание запроса в Retrofit2 Callback в Android Studio - PullRequest
0 голосов
/ 29 января 2020

Я пытаюсь поправиться с помощью запросов на модернизацию и пользовательских обратных вызовов в моем приложении. Когда я вхожу в систему, мой бэкэнд генерирует токен для пользователя. Каждые X seconds/minutes мой токен становится устаревшим, и мне нужно генерировать / refre sh новый токен, когда я делаю новый запрос.

У меня проблема в том, что когда токен устарел, я могу ' t сгенерировать новый перед запросом.

In 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

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());
   }
}

Похоже, что я выполняю основной запрос до (или во время) запроса токена refre sh.

Как я могу улучшить свой код, чтобы выполнить этот шаг за шагом (refre * 1025) * токен, тогда сделайте основной запрос)?

Спасибо за помощь.

Ответы [ 2 ]

1 голос
/ 30 января 2020

Ниже мы помним, что при использовании динамической интеграции c заголовков (токены).

  1. Токен может истечь в любое время, когда мы используем приложение
  2. Ошибка 401 в API-интерфейсах .

, поэтому нам нужен обратный вызов для обнаружения истечения токена при вызове API, поэтому мы используем Authendicator. Он сработает, когда наш API получит 401 (добавьте класс аутентификатора, если вы отправили токен с API) .

Если вы получаете 401, позвоните в ваш refre sh 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();
        }
    }

Затем добавьте Authendicator в ваш okhttp клиент

 .authenticator(new TokenAuthenticator())
0 голосов
/ 03 февраля 2020

Итак, я нашел нестандартное решение, которое работает. Я надеюсь, что помогу людям с этим. Я хотел максимально упростить запросы, вот так выглядит HTTP-запрос:

MainActivity. 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

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);
    }
}

РЕДАКТИРОВАТЬ: я забыл код:

RetrofitClientInstance. 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

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...