我正在尝试与API进行交互,并通过将当前电子邮件(存储在SharedPrefs中)与从API返回的电子邮件进行比较来检查JSON响应,以查看用户是否存在该API。如果用户存在,则标记设置为 true ,以便应用程序不发送POST请求以保存新用户,如果 false ,则用户将被保存在API中。
所以,这是 UEC(UserExistenceChecker)类
public class MainActivity{
SharedPreferences sharedPref =
PreferenceManager.getDefaultSharedPreferences(getBaseContext());
UEC uec = new UEC(sharedPref);
boolean userExists = uec.checkIfUserExists();
if (userExists) {
Log.d("USERSTATUS", String.valueOf(sharedPref.getInt("userID", 0)));
} else {
Log.d("USERSTATUS", "FALSE:DOESNT EXIST");
Log.d("USERSTATUS", String.valueOf(sharedPref.getInt("userID", 0)));
}
}
在本课程中,我制作了一个布尔标志,其默认值为 false
这就是我从 MainActivity.java
中调用方法 checkIfUserExists()的方法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
现在,问题在于,根据日志,其他条件始终为 true ,因为标记始终为 false 即使我在 checkIfUserExists()方法中将其设置为 true 。
和日志有趣的是这个
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
首先出现,然后在日志
之后出现在日志中{{1}}
表示它检测到电子邮件并设置了sharedpref 但国旗仍然是假的。
答案 0 :(得分:1)
通过快速查看代码,看起来enqueue方法导致在调用checkIfUserExists()
方法后布尔值只能更改为true。
这是您在日志中看到的内容,由于enqueue方法的异步特性,onResponse()
和onFailure()
中的所有代码仅在后台线程中的所有其他代码之后执行
为了避免这种情况,您可以实现一个回调方法,以便每当onResponse()
方法完成时,您都可以调用该方法来检查用户是否存在。在下面的代码中,回调方法是onUserExists()
,它替换了真正的布尔标志,如果用户不存在,我还会包含一个else语句,这将触发第二个回调,即onUserDoesNotExist()
方法。这些回调方法将在那里的onUserExists()
和onUserDoesNotExist()
方法中触发MainActivity中的代码。
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;
}
为此,您需要创建OnUserExistsCallback接口。
public interface OnUserExistsCallback {
void onUserExists();
void onUserDoesNotExist();
}
最后,这就是您的MainActivity现在的样子。
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)));
}
);
}
不确定这是否会编译并成功运行,因为我自己没有运行此代码。希望它会解决你的问题。
答案 1 :(得分:0)
该行为是由checkUser.enqueue(new Callback<List<SavePlace>>()
的异步执行引起的。因此,当您从checkIfUserExists()
调用此方法时,您的执行线程将不会等待checkUser.enqueue()
完成。相反,它将立即转到下一行并返回当前标志值false。 checkUser.enqueue()
将在后台线程中执行,您将以onResponse()
方法获得结果。根据您的代码,行为是正确的。请尝试异步处理场景,因为这是网络呼叫的推荐方法。
答案 2 :(得分:0)
问题是你在调用这个方法时正在处理异步函数调用
uec.checkIfUserExists();
此函数中的代码以正常方式执行,直到您在此处调用api的行
final Call<List<SavePlace>> checkUser = apiInterfaceSavePlace.getSavePlaces();
在后台线程中进行web api调用,并且您的函数以正常方式执行并返回,这意味着您将获得标记为false值。 当后台任务完成后,然后是
中的代码public void onResponse()
执行方法,这是一种回调方法,您可以使用true flag获取值。
<强>解决方案强>
您应该等待api调用完成,然后对用户是否存在执行任何检查。 因此,一种简单的方法是将用户存在的内部检查onResponse()回调方法本身。
如果你想在你的活动或片段中处理它,你可以创建自己的回调方法并将其传递给checkIfUserExists();
像这样的东西
public interface MyInterface{
public void onCallback(boolean isUserExists);
}
并在您的活动中
uec.checkIfUserExists(
new MyInterface(){
@Override
public void onCallback(boolean isUserExists){
if (isUserExists) {
//your code
}
else{
//your code
}
}
}
);
像你这样更改checkIfUserExists()方法
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
}
});
}