使用发送到 API 的请求检查用户名可用性(改造)

Checking username availability by using a request sent to the API (Retrofit)

我正在尝试创建一个简单的应用程序来处理登录和注册过程。 我在验证注册表单时遇到问题。我想检查输入的用户名是否可用。我为此目的创建了一个端点,其中 returns JSON 具有单个值 {"bool" : "true"} 或 {"bool" : "false"}。

我使用以下函数验证提供的数据:

private boolean validateUsername(){
    String val = usernameInput.getEditText().getText().toString().trim();

    checkIfUsernameIsAvailable(val);

    if(val.isEmpty()){
        usernameInput.setError("Field can not be empty");
        return false;
    } else if(val.length() > 20) {
        usernameInput.setError("Username is too large");
        return false;
    } else if(isUsernameInUse) {
        usernameInput.setError("Username is already in use");
        return false;
    } else {
        usernameInput.setError(null);
        usernameInput.setErrorEnabled(false);
        return true;
    }
}

除检查用户可用性外,一切正常。即:发送请求到API的线程在执行IF之前有时会执行失败。

请求是这样发送的:

private void checkIfUsernameIsAvailable(String username){
    ExistsUsernameDTO existsUsernameDTO = new ExistsUsernameDTO(username);
    Call<BooleanDTO> call = userService.existsByUsername(existsUsernameDTO);

    call.enqueue(new Callback<BooleanDTO>() {

        @Override
        public void onResponse(Call<BooleanDTO> call, Response<BooleanDTO> response) {
            if (response.isSuccessful()){
                isUsernameInUse = response.body().getBool();
            } else {
                Toast.makeText(RegisterActivity.this, "username_check_failed", Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFailure(Call<BooleanDTO> call, Throwable t) {
            Toast.makeText(RegisterActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
        }
    });
}

这是在单击注册按钮时启动的功能:

public void callNextRegisterScreen(View view) {

    if (!validateUsername()){
        return;
    }

    Intent intent = new Intent(getApplicationContext(), RegisterUserDetailsActivity.class);

    Pair[] pairs = new Pair[4];
    pairs[0] = new Pair<View, String>(backBtn, "transition_back_arrow_btn");
    pairs[1] = new Pair<View, String>(titleText, "transition_title_text");
    pairs[2] = new Pair<View, String>(nextBtn, "transition_next_btn");
    pairs[3] = new Pair<View, String>(loginBtn, "transition_login_btn");

    ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(RegisterActivity.this, pairs);
    startActivity(intent, activityOptions.toBundle());
}

如何让验证等待查询执行或如何以更好的方式执行此验证?

当您的“用户名可用”网络请求 returns 成功时,您需要导航到下一个屏幕,例如,您可以将代码重构为如下所示:

public void callNextRegisterScreen() {
    validateUsername()
}

private void validateUsername(){
    String val = usernameInput.getEditText().getText().toString().trim();

    if(val.isEmpty()){
        usernameInput.setError("Field can not be empty");
        return;
    } else if(val.length() > 20) {
        usernameInput.setError("Username is too large");
        return;
    } else if(isUsernameInUse) {
        usernameInput.setError("Username is already in use");
        return;
    }

    checkIfUsernameIsAvailable(val);
}

private void checkIfUsernameIsAvailable(String username){
    ExistsUsernameDTO existsUsernameDTO = new ExistsUsernameDTO(username);
    Call<BooleanDTO> call = userService.existsByUsername(existsUsernameDTO);

    call.enqueue(new Callback<BooleanDTO>() {

        @Override
        public void onResponse(Call<BooleanDTO> call, Response<BooleanDTO> response) {
            if (response.isSuccessful()){
                isUsernameInUse = response.body().getBool();
                if(isUsernameInUse)
                  Toast.makeText(RegisterActivity.this, "username in use",Toast.LENGTH_LONG).show();
                else
                  navigateNextRegisterScreen()
            } else {
                Toast.makeText(RegisterActivity.this, "username_check_failed", Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFailure(Call<BooleanDTO> call, Throwable t) {
            Toast.makeText(RegisterActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
        }
    });
}


public void navigateNextRegisterScreen(){

    Intent intent = new Intent(getApplicationContext(), RegisterUserDetailsActivity.class);

    Pair[] pairs = new Pair[4];
    pairs[0] = new Pair<View, String>(backBtn, "transition_back_arrow_btn");
    pairs[1] = new Pair<View, String>(titleText, "transition_title_text");
    pairs[2] = new Pair<View, String>(nextBtn, "transition_next_btn");
    pairs[3] = new Pair<View, String>(loginBtn, "transition_login_btn");

    ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(RegisterActivity.this, pairs);
    startActivity(intent, activityOptions.toBundle());
}