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

Java 使用发送到API的请求检查用户名可用性(改装),java,android,rest,retrofit,Java,Android,Rest,Retrofit,我正在尝试创建一个简单的应用程序来处理登录和注册过程。 我在验证我的注册表格时遇到问题。我想检查输入的用户名是否可用。我为此创建了一个端点,它返回带有单个值{“bool”:“true”}或{“bool”:“false”}的JSON 我使用以下功能验证提供的数据: private boolean validateUsername(){ String val = usernameInput.getEditText().getText().toString().trim(); che

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

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

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();
        }
    });
}
private void checkIfUserName可用(字符串用户名){
ExistsUsernameDTO ExistsUsernameDTO=新的ExistsUsernameDTO(用户名);
Call Call=userService.existsByUsername(existsusernamedo);
call.enqueue(新回调(){
@凌驾
公共void onResponse(调用、响应){
if(response.issusccessful()){
isUsernameInUse=response.body().getBool();
}否则{
Toast.makeText(RegisterActivity.this,“用户名检查失败”,Toast.LENGTH.show();
}
}
@凌驾
失败时公共无效(调用调用,可丢弃的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());
}
public void callnextregister屏幕(视图){
如果(!validateUsername()){
返回;
}
Intent Intent=new Intent(getApplicationContext(),RegisterUserDetailsActivity.class);
Pair[]pairs=新的Pair[4];
pairs[0]=新对(backBtn,“transition\u back\u arrow\u btn”);
pairs[1]=新的pairs(titleText,“transition_title_text”);
pairs[2]=新对(nextBtn,“transition_next_btn”);
pairs[3]=新对(loginBtn,“transition\u login\u btn”);
ActivityOptions ActivityOptions=ActivityOptions.MakeScenetTransitionAnimation(RegisterActivity.this,成对);
startActivity(intent,activityOptions.toBundle());
}

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

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

public void callNextRegisterScreen(){
validateUsername()
}
私有void validateUsername(){
String val=usernameInput.getEditText().getText().toString().trim();
if(val.isEmpty()){
usernameInput.setError(“字段不能为空”);
返回;
}否则如果(值长度()>20){
usernameInput.setError(“用户名太大”);
返回;
}else if(isUsernameInUse){
usernameInput.setError(“用户名已在使用”);
返回;
}
CheckIfUserName可用(val);
}
private void CheckIfUserName可用(字符串用户名){
ExistsUsernameDTO ExistsUsernameDTO=新的ExistsUsernameDTO(用户名);
Call Call=userService.existsByUsername(existsusernamedo);
call.enqueue(新回调(){
@凌驾
公共void onResponse(调用、响应){
if(response.issusccessful()){
isUsernameInUse=response.body().getBool();
if(isUsernameInUse)
Toast.makeText(RegisterActivity.this,“用户名正在使用”,Toast.LENGTH_LONG.show();
其他的
navigateNextRegisterScreen()
}否则{
Toast.makeText(RegisterActivity.this,“用户名检查失败”,Toast.LENGTH.show();
}
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
Toast.makeText(RegisterActivity.this,t.getMessage(),Toast.LENGTH_LONG.show();
}
});
}
public void navigateNextRegisterScreen(){
Intent Intent=new Intent(getApplicationContext(),RegisterUserDetailsActivity.class);
Pair[]pairs=新的Pair[4];
pairs[0]=新对(backBtn,“transition\u back\u arrow\u btn”);
pairs[1]=新的pairs(titleText,“transition_title_text”);
pairs[2]=新对(nextBtn,“transition_next_btn”);
pairs[3]=新对(loginBtn,“transition\u login\u btn”);
ActivityOptions ActivityOptions=ActivityOptions.MakeScenetTransitionAnimation(RegisterActivity.this,成对);
startActivity(intent,activityOptions.toBundle());
}

虽然从逻辑角度来看,我对android开发不太熟悉,但我想说的是,只有在检查完空白和长度之后,您才应该发送此检查。这意味着如果这两个检查失败,那么首先就不需要发送调用。是的,我希望检查函数在空性和长度验证之后执行,但我不知道如何使CheckIfUserName可用函数返回布尔值(这很困难,因为它使用内部类)。另外,在另一个论坛帖子中,人们写道异步函数应该返回void,而不是boolean。我认为如果checkIfUsernameIsAvailable方法成功,应该触发callNextRegisterScreen。非常感谢!你的解决方案帮了大忙;)非常欢迎,如果答案对您有帮助,请选择“接受”或“向上投票”,以便其他人能够识别问题和解决方案
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());
}