简体   繁体   中英

Retrofit Asynchronous call on condition

I have to receive a token from an API, store it in shared preferences and make a call to the API only if the token has expired. The token expires after 200000 seconds. Basically I'm try to follow these instructions:

  1. Generate a token and store it in a session
  2. Store the time you generated the token aka current time
  3. Check token expiry against the current time whenever you make an API call
  4. Re-authenticate and generate a new token in the background if token expiry is greater than the current time

However the first API call is made even before the token is generated and null is passed as token, then the token is generated and stored in Shared Preferences. So it just doesn't work the first time, and then works. Is there a problem with using if conditions and asynchronous Retrofit calls.

Here's the function I used to create a token

public void getToken(){
    Credentials credentials=new Credentials("public_user","public_pass");

    Call<Authentication> call=service.getToken(credentials);
    call.enqueue(new Callback<Authentication>() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onResponse(Call<Authentication> call, Response<Authentication> response) {

            if (response.body().getCode() != 0) {

                 token = response.body().getDocument();

                SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx.getApplicationContext());
                SharedPreferences.Editor editor=preferences.edit();
                editor.putString("token",token).commit();
                tokenExpires=Instant.now().plus(Duration.ofSeconds(200000));
                long millis=tokenExpires.toEpochMilli();
                editor.putLong("token_expiry_time",millis).commit();
                String this_token=preferences.getString("token",null);

            }
        }

        @Override
        public void onFailure(Call<Authentication> call, Throwable t) {

        }
    });
}

And here's how I am calling this function and using it to call the API

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    
     service = ApiClient.getClientStats().create(ApiInterface.class);
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx.getApplicationContext());
    String retrievedToken  = preferences.getString("token",null);
    long token_expiry_time=preferences.getLong("token_expiry_time",0);

    if(retrievedToken==null || token_expiry_time==0 || token_expiry_time<=Instant.now().toEpochMilli()) {
        getToken();
        retrievedToken=token;
    }

    else {


        Call<Stat> call = service.getMapData("Bearer " + retrievedToken);
        call.enqueue(new Callback<Stat>() {
            @Override
            public void onResponse(Call<Stat> call, Response<Stat> response) {

                


                }
            }

            @Override
            public void onFailure(Call<Stat> call, Throwable t) {

            }
        });
    }

When you call getToken() retrofit runs it on another thread. While this is happening the main thread continues its execution in the if statement and assigns null to retrieveToken as at that time token is null, that is the reason why you have the first null. Then retrofit completes it exec and sets the shared preferences. You can use LiveData to observe for the result before making other queries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM