Android 布尔标志始终为false

Android 布尔标志始终为false,android,retrofit2,android-sharedpreferences,Android,Retrofit2,Android Sharedpreferences,我试图与API交互,并通过比较当前电子邮件(存储在SharedPrefs中)和API返回的电子邮件来检查JSON响应,从而查看用户是否存在于该API上。如果用户存在,则设置一个标志true,这样应用程序就不会发送POST请求来保存新用户,如果该标志为false,则用户将保存在API中 因此,这是UEC(UserExistenceChecker)类 public class UEC extends AppCompatActivity { List<SavePlace> userInf

我试图与API交互,并通过比较当前电子邮件(存储在SharedPrefs中)和API返回的电子邮件来检查JSON响应,从而查看用户是否存在于该API上。如果用户存在,则设置一个标志true,这样应用程序就不会发送POST请求来保存新用户,如果该标志为false,则用户将保存在API中

因此,这是UEC(UserExistenceChecker)类

public class UEC extends AppCompatActivity {

List<SavePlace> userInfo;

String name;
boolean flag;
SharedPreferences sharedPref;

public UEC(SharedPreferences sharedPref){
    this.sharedPref = sharedPref;
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

public boolean checkIfUserExists() {

    email = sharedPref.getString("userEmail", "");

    Retrofit retrofitCheckUser = ApiClientSavePlace.getClient();
    ApiInterfaceSavePlace apiInterfaceSavePlace = retrofitCheckUser.create(ApiInterfaceSavePlace.class);
    final Call<List<SavePlace>> checkUser = apiInterfaceSavePlace.getSavePlaces();

    checkUser.enqueue(new Callback<List<SavePlace>>() {
        @Override
        public void onResponse(Call<List<SavePlace>> call, Response<List<SavePlace>> response) {
            userInfo = response.body();
            try {
                if(userInfo.size()!=0){
                    for (int i = 0; i <= userInfo.size(); i++) {
                        String emailReturned = userInfo.get(i).getEmail();
                        Log.d("response", "email returned: " + emailReturned);
                        Log.d("sharedpref", "email: " + email);
                        if (emailReturned.equals(email)) {
                        Log.d("response:", "email match?: " + emailReturned.equals(email));
                            flag = true;
                            SharedPreferences.Editor editor = sharedPref.edit();
                            editor.putInt("userID", userInfo.get(i).getId());
                            Log.d("ID returned", String.valueOf(userInfo.get(i).getId()));
                            editor.apply();
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<List<SavePlace>> call, Throwable throwable) {
            Log.d("RESPONSE", "FAILED CHECKING USER ID/SOMETHING HAPPENED");
        }
    });
    return flag;
}

}
现在的问题是,根据日志,else条件始终为true,因为标志始终为false,即使我在checkIfUserExists()方法中将其设置为true

日志的有趣之处在于

05-13 15:27:54.278 1613-1613/xyz.gautamhans.locus D/USERSTATUS: FALSE:DOESNT 
EXIST
05-13 15:27:54.278 1613-1613/xyz.gautamhans.locus D/USERSTATUS: 12
首先出现,然后在上面的日志之后的日志中出现

05-13 15:27:55.746 1613-1613/xyz.gautamhans.locus D/response: email 
returned: some-email@gmail.com
05-13 15:27:55.749 1613-1613/xyz.gautamhans.locus D/sharedpref: email: 
some-email@gmail.com
05-13 15:27:55.749 1613-1613/xyz.gautamhans.locus D/response: email 
returned: some-email@gmail.com
05-13 15:27:55.749 1613-1613/xyz.gautamhans.locus D/sharedpref: email: 
some-email@gmail.com
05-13 15:27:55.749 1613-1613/xyz.gautamhans.locus D/response: email match?: 
true
05-13 15:27:55.749 1613-1613/xyz.gautamhans.locus D/ID returned: 12
这意味着它检测到了电子邮件并设置了sharedpref
但这面旗帜仍然是假的

该行为是由于异步执行了
checkUser.enqueue(new Callback()
。因此,当您从
checkIfUserExists()
调用此方法时,您的执行线程将不会等待
checkUser.enqueue()
完成。相反,它将立即转到下一行并返回当前标志值,该值为false。
checkUser.enqueue()
将在后台线程中执行,您将在
onResponse()中获得结果
method。根据您的代码,该行为是正确的。请尝试异步处理场景,因为这是网络调用的推荐方法。

快速查看您的代码,似乎enqueue方法导致布尔值仅在调用
checkIfUserExists()后才更改为true
方法

这是您在日志中看到的,由于排队方法的异步性质,您的
onResponse()
onFailure()
中的所有代码仅在后台线程中的所有其他代码之后执行

为了避免这种情况,您可以实现回调方法,以便在完成
onResponse()
方法时调用该方法以检查用户是否存在。在下面的代码中,回调方法是
onUserExists()
替换了true boolean标志,我还包括了一个else语句,如果用户不存在,它将触发第二次回调,
onUserDoesNotExist()
方法。这些回调方法将触发
onUserExists()
onUserDoesNotExist()中main活动中的代码
方法

public void checkIfUserExists(OnUserExistsCallback onUserExistsCallback) {

    email = sharedPref.getString("userEmail", "");

    Retrofit retrofitCheckUser = ApiClientSavePlace.getClient();
    ApiInterfaceSavePlace apiInterfaceSavePlace = retrofitCheckUser.create(ApiInterfaceSavePlace.class);
    final Call<List<SavePlace>> checkUser = apiInterfaceSavePlace.getSavePlaces();
    OnUserExistsCallback callback = onUserExistsCallback;
    checkUser.enqueue(new Callback<List<SavePlace>>() {
        @Override
        public void onResponse(Call<List<SavePlace>> call, Response<List<SavePlace>> response) {
            userInfo = response.body();
            try {
                if(userInfo.size()!=0){
                    for (int i = 0; i <= userInfo.size(); i++) {
                        String emailReturned = userInfo.get(i).getEmail();
                        Log.d("response", "email returned: " + emailReturned);
                        Log.d("sharedpref", "email: " + email);
                        if (emailReturned.equals(email)) {
                        Log.d("response:", "email match?: " + emailReturned.equals(email));
                            SharedPreferences.Editor editor = sharedPref.edit();
                            editor.putInt("userID", userInfo.get(i).getId());
                            Log.d("ID returned", String.valueOf(userInfo.get(i).getId()));
                            editor.apply();
                            callback.onUserExists();
                            break;
                        } else {
                            callback.onUserDoesNotExist();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<List<SavePlace>> call, Throwable throwable) {
            Log.d("RESPONSE", "FAILED CHECKING USER ID/SOMETHING HAPPENED");
        }
    });
    return flag;
}
最后,这就是您的主要活动现在的样子

public class MainActivity {

    SharedPreferences sharedPref =
        PreferenceManager.getDefaultSharedPreferences(getBaseContext());

    UEC uec = new UEC(sharedPref);
    uec.checkIfUserExists(new OnUserExistsCallback() {
            @Override
            public void onUserExists() {
                Log.d("USERSTATUS", String.valueOf(sharedPref.getInt("userID", 0)));
            }

            @Override
            public void onUserDoesNotExist() {
                Log.d("USERSTATUS", "FALSE:DOESNT EXIST");
                Log.d("USERSTATUS", String.valueOf(sharedPref.getInt("userID", 0)));
            }

        );
    }

我不确定这段代码是否能成功编译和运行,因为我自己还没有运行过这段代码。希望它能解决您的问题。

问题是,调用此方法时,您正在处理异步函数调用

uec.checkIfUserExists();
此函数中的代码以正常方式执行,直到在此处进行api调用的那一行

final Call<List<SavePlace>> checkUser = apiInterfaceSavePlace.getSavePlaces();
方法执行,这是一个回调方法,您可以使用true标志获取值

解决方案

您应该等待api调用完成,然后对用户是否存在执行任何检查。 因此,一种简单的方法是将用户存在检查放在onResponse()回调方法本身中

如果您想在活动或片段中处理它,您可以创建自己的回调方法并将其传递给
checkIfUserExists();

像这样的

public interface MyInterface{
    public void onCallback(boolean isUserExists);
}
public void checkIfUserExists(final MyInterface myInterface) {
    //your code
    checkUser.enqueue(new Callback<List<SavePlace>>(final MyInterface myInterface) {
        @Override
        public void onResponse(Call<List<SavePlace>> call, Response<List<SavePlace>> response) {
            userInfo = response.body();
            try {
               //your code
                    if (emailReturned.equals(email)) {
                        flag = true;
                    }
                    //pass your flag to callback method here.
                    myInterface.onCallback(flag);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<List<SavePlace>> call, Throwable throwable) {
          //Handle failure
        }
    });
}
在你的活动中

uec.checkIfUserExists(
    new MyInterface(){
        @Override
        public void onCallback(boolean isUserExists){
            if (isUserExists) {
                //your code
            }
            else{
                //your code
            }
        }
    }
);
对checkIfUserExists()方法进行如下更改

public interface MyInterface{
    public void onCallback(boolean isUserExists);
}
public void checkIfUserExists(final MyInterface myInterface) {
    //your code
    checkUser.enqueue(new Callback<List<SavePlace>>(final MyInterface myInterface) {
        @Override
        public void onResponse(Call<List<SavePlace>> call, Response<List<SavePlace>> response) {
            userInfo = response.body();
            try {
               //your code
                    if (emailReturned.equals(email)) {
                        flag = true;
                    }
                    //pass your flag to callback method here.
                    myInterface.onCallback(flag);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<List<SavePlace>> call, Throwable throwable) {
          //Handle failure
        }
    });
}
public void checkIfUserExists(最终MyInterface MyInterface){
//你的代码
checkUser.enqueue(新回调(最终MyInterface MyInterface){
@凌驾
公共void onResponse(调用、响应){
userInfo=response.body();
试一试{
//你的代码
if(emailReturned.equals(email)){
flag=true;
}
//在此处将您的标志传递给回调方法。
myInterface.onCallback(标志);
}
}捕获(例外e){
e、 printStackTrace();
}
}
@凌驾
失败时公共无效(调用、可丢弃){
//处理失败
}
});
}

是的,我现在明白了。谢谢。你能想到这个问题的可能解决方案吗?你好。谢谢你的回答。我在实现你的解决方案时遇到了困难。请参见此屏幕截图:@mnmncp first
onUserExistsCallback
应该是大写字母“O”而不是小写字母“O”。你的接口名称也有小写字母“O”o'在beginning@mnmncp
public void checkIfUserExists(OnUserExistsCallback OnUserExistsCallback)
您没有包含参数needed抱歉,这是我的错误。因此,我已经实现了解决方案,但在日志中得到了这一点:感谢您的响应。您能告诉我如何使用接口调用checkIfUserExists()或enqueue方法中的onCallBack方法吗?
public void checkIfUserExists(final MyInterface myInterface) {
    //your code
    checkUser.enqueue(new Callback<List<SavePlace>>(final MyInterface myInterface) {
        @Override
        public void onResponse(Call<List<SavePlace>> call, Response<List<SavePlace>> response) {
            userInfo = response.body();
            try {
               //your code
                    if (emailReturned.equals(email)) {
                        flag = true;
                    }
                    //pass your flag to callback method here.
                    myInterface.onCallback(flag);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<List<SavePlace>> call, Throwable throwable) {
          //Handle failure
        }
    });
}