简体   繁体   中英

Android - Task is not running when it should

I am using Backendless to store my app user's data. Backendless only has the option to make either your email or username unique. I made my username field unique and that is what the user will use to log in. The emails can be reused so I am making a method before registration to check if the email exists.

This is the createUser method, this starts off and calls the method to check for email availability as soon as it starts:

private void createUser() {
    showProgressDialog();

    if (isEmailAvailable(inputEmail.getText().toString().trim())) {
        BackendlessUser user = new BackendlessUser();
        user.setProperty(BackendSettings.USERNAME_KEY, inputUsername.getText().toString().trim());
        user.setEmail(inputEmail.getText().toString().trim());
        user.setPassword(inputPassword.getText().toString());

        Backendless.UserService.register(user, new AsyncCallback<BackendlessUser>() {
            @Override
            public void handleResponse(BackendlessUser backendlessUser) {
                hideProgressDialog();
                Toast.makeText(CreateAccountActivity.this, BackendSettings.REGISTER_SUCCESS_MESSAGE, Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(CreateAccountActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
            }

            @Override
            public void handleFault(BackendlessFault backendlessFault) {
                hideProgressDialog();
                String errorCode = backendlessFault.getCode();
                String errorMessage;
                switch (errorCode) {
                    case "3040":
                        errorMessage = BackendSettings.ERROR_3040;
                        break;
                    case "3033":
                        errorMessage = BackendSettings.ERROR_3033;
                        break;
                    default:
                        errorMessage = "An unknown error occurred. Try again.";
                }
                Toast.makeText(CreateAccountActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
            }
        });
    } else {
        hideProgressDialog();
        Toast.makeText(CreateAccountActivity.this, BackendSettings.ERROR_EMAIL_TAKEN, Toast.LENGTH_SHORT).show();
    }
}

This is the method that checks for the email availability:

private boolean isAvailable;
private boolean isEmailAvailable(String email) {
    isAvailable = false;

    String whereClause = "email = '" + email + "'";
    BackendlessDataQuery dataQuery = new BackendlessDataQuery();
    dataQuery.setWhereClause(whereClause);
    Backendless.Persistence.of(BackendlessUser.class).find(dataQuery, new AsyncCallback<BackendlessCollection<BackendlessUser>>() {
        @Override
        public void handleResponse(BackendlessCollection<BackendlessUser> userBackendlessCollection) {
            isAvailable = userBackendlessCollection.getData().isEmpty();
        }

        @Override
        public void handleFault(BackendlessFault backendlessFault) {
            Toast.makeText(CreateAccountActivity.this, backendlessFault.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });
    return isAvailable;
}

Okay, so I always get the message that the email is already taken, even if it is not. So I decided to put a Toast message in the handleResponse method for isEmailAvailble . I made it print if the email was available or not. So I first got the message from the else clause in createUser saying that the email was already taken and then I got the message from the isEmailAvailable method. It seems that the isEmailAvailable method is being ran afterwards. I am not sure what is going wrong with it.

Woa! The error is in isEmailAvailable method.

Find if asyncronous method. It works like that: you call it, it begins to work and returns immediately, before any actually results. Later it calls the callback methods. So, when you do

    return isAvailable;

isAvailable is always false on that line because it is still not changed.

You should do some async work. 1. call Backendless.Persistence.of(BackendlessUser.class).find(...) 2. wait for answer. You will know the result only in

   public void handleResponse(BackendlessCollection<BackendlessUser> userBackendlessCollection) {
       isAvailable = userBackendlessCollection.getData().isEmpty();
   }

3. do the rest of job just after

    isAvailable = userBackendlessCollection.getData().isEmpty();

create a method doCreateUser, put the body of you "if" into it and call it from handleResponse, after isAvailable = userBackendlessCollection.getData().isEmpty();

use this code:

    private void createUser() {
        showProgressDialog();
        checkEmailAvailable(inputEmail.getText().toString().trim());
    }

    private void checkEmailAvailable(String email) {
        String whereClause = "email = '" + email + "'";
        BackendlessDataQuery dataQuery = new BackendlessDataQuery();
        dataQuery.setWhereClause(whereClause);
        Backendless.Persistence.of(BackendlessUser.class).find(dataQuery, new AsyncCallback<BackendlessCollection<BackendlessUser>>() {
            @Override
            public void handleResponse(BackendlessCollection<BackendlessUser> userBackendlessCollection) {
                isAvailable = userBackendlessCollection.getData().isEmpty();
                if (isAvailable){
                    doCreateuser();
                } else {
                    hideProgressDialog();
                    Toast.makeText(CreateAccountActivity.this, BackendSettings.ERROR_EMAIL_TAKEN, Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void handleFault(BackendlessFault backendlessFault) {
                Toast.makeText(CreateAccountActivity.this, backendlessFault.getMessage(), Toast.LENGTH_SHORT).show();
                hideProgressDialog();
            }
        });
    }

    private void doCreateuser(){
        BackendlessUser user = new BackendlessUser();
        user.setProperty(BackendSettings.USERNAME_KEY, inputUsername.getText().toString().trim());
        user.setEmail(inputEmail.getText().toString().trim());
        user.setPassword(inputPassword.getText().toString());

        Backendless.UserService.register(user, new AsyncCallback<BackendlessUser>() {
            @Override
            public void handleResponse(BackendlessUser backendlessUser) {
                hideProgressDialog();
                Toast.makeText(CreateAccountActivity.this, BackendSettings.REGISTER_SUCCESS_MESSAGE, Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(CreateAccountActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
            }

            @Override
            public void handleFault(BackendlessFault backendlessFault) {
                hideProgressDialog();
                String errorCode = backendlessFault.getCode();
                String errorMessage;
                switch (errorCode) {
                    case "3040":
                        errorMessage = BackendSettings.ERROR_3040;
                        break;
                    case "3033":
                        errorMessage = BackendSettings.ERROR_3033;
                        break;
                    default:
                        errorMessage = "An unknown error occurred. Try again.";
                }
                Toast.makeText(CreateAccountActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
            }
        });
    }

The calls to Backendless are asynchron and thats why your method always return the value isAvailable is initialised with(here false). You need to synchronize for example with a Semaphore to block before return the proper value.

private boolean isEmailAvailable(String email) {
boolean isAvailable = false;
String whereClause = "email = '" + email + "'";
final Semaphore s = new Semaphore(0);
BackendlessDataQuery dataQuery = new BackendlessDataQuery();
dataQuery.setWhereClause(whereClause);

Backendless.Persistence.of(BackendlessUser.class).find(dataQuery, new AsyncCallback<BackendlessCollection<BackendlessUser>>() {
    @Override
    public void handleResponse(BackendlessCollection<BackendlessUser> userBackendlessCollection) {
        isAvailable = userBackendlessCollection.getData().isEmpty();
        s.release();
    }

    @Override
    public void handleFault(BackendlessFault backendlessFault) {
        Toast.makeText(CreateAccountActivity.this, backendlessFault.getMessage(), Toast.LENGTH_SHORT).show();
        s.release();
    }
});
try{
    s.aquire();
}catch(Exception e){
}
return isAvailable;

}

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