ethanzh ethanzh - 4 months ago 14
Android Question

How To Deal With Asynchronous Login to REST API?

I'm trying to write the login portion of my android app that authenticates with my REST API. This is what I have currently

LogInTask boolean function

boolean LogInTask(String username, String password){



AuthOrNot.setCurrent(true);
Log.wtf("START", "" + AuthOrNot.getCurrent());

UserAPI.Factory.getInstance().authenticateUser("testuser", "password").enqueue(new Callback<TokenJSON>() {
@Override
public void onResponse(Call<TokenJSON> call, Response<TokenJSON> response) {

try{
String token = response.body().getToken();
Log.wtf("WORKS",""+ token);

AuthOrNot.setCurrent(false);

Log.wtf("AUTH", "" + AuthOrNot.getCurrent());


}catch (NullPointerException t){
Log.wtf("NO", "Didn't work, most likely incorrect username+password");
AuthOrNot.setCurrent(false);
t.printStackTrace();
}
}

@Override
public void onFailure(Call<TokenJSON> call, Throwable t) {
Log.wtf("FAIL",""+t.getMessage());
AuthOrNot.setCurrent(false);
}
});

Log.wtf("AUTH", "" + AuthOrNot.getCurrent());

return AuthOrNot.getCurrent();
}


I know this is probably not the best way to go about making this, which is why I am here now. What is happening is that the network request takes 1-2 seconds, by which time the code is already at the bottom, and AuthoOrNot.getCurrent() == true, which means that the next activity is launched whether or not the username+password combo is correct.

Answer

You can create an interface to use it as a callback. The interface may look like this:

public Interface LoginCallback{
    void onLoginSuccess();
    void onLoginFailure();
}

Then update your code to something like this:

void LogInTask(String username, String password, final LoginCallback callback){
// this isnt't needed: AuthOrNot.setCurrent(true);
//Log.wtf("START", "" + AuthOrNot.getCurrent());

UserAPI.Factory.getInstance().authenticateUser("testuser", "password").enqueue(new Callback<TokenJSON>() {
    @Override
    public void onResponse(Call<TokenJSON> call, Response<TokenJSON> response) {

        try{
            String token = response.body().getToken();
            Log.wtf("WORKS",""+ token);

            callback.onLoginSuccess();

            //Log.wtf("AUTH", "" + AuthOrNot.getCurrent());


        }catch (NullPointerException t){
            Log.wtf("NO", "Didn't work, most likely incorrect username+password");
            callback.onLoginFailure();
            t.printStackTrace();
        }
    }

    @Override
    public void onFailure(Call<TokenJSON> call, Throwable t) {
        Log.wtf("FAIL",""+t.getMessage());
        callback.onLoginFailure();
    }
});

//Log.wtf("AUTH", "" + AuthOrNot.getCurrent());

//nothing to return;
}

Then wherever you are calling the LogInTask method:

LoginTask("user", "password", new LoginCallback() {
    void onLoginSuccess(){
    //at this point you are logged in
    }
    void onLoginFailure(){
    //at this point the login has failed
    }
});

P.S: method names should start in lower case, so "LoginTask()" should actually be "loginTask()"

Comments