布尔标志始终为假
Posted
技术标签:
【中文标题】布尔标志始终为假【英文标题】:boolean flag is always false 【发布时间】:2017-10-12 21:55:48 【问题描述】:我正在尝试与 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;
在这个类中,我做了一个 boolean flag 默认值 false
这就是我从 MainActivity.java
调用方法 checkIfUserExists() 的方式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)));
现在,问题在于,根据日志,else 条件始终为 true,因为 flag 始终为 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
这意味着它检测到了电子邮件并设置了共享首选项 但标志仍然是假的。
【问题讨论】:
【参考方案1】:快速查看您的代码,看起来 enqueue 方法导致布尔值仅在您调用 checkIfUserExists()
方法后才更改为 true。
这是您在日志中看到的内容,由于 enqueue 方法的异步特性,您的 onResponse()
和 onFailure()
中的所有代码仅在后台线程中的所有其他代码之后执行。
为了帮助避免这种情况,您可以实现一个回调方法,以便在 onResponse()
方法完成时调用该方法来检查用户是否存在。在下面的代码中,回调方法是onUserExists()
,它替换了真正的布尔标志,如果用户不存在,我还包含一个else语句,这将触发第二个回调,onUserDoesNotExist()
方法。这些回调方法会触发 MainActivity 中 onUserExists()
和 onUserDoesNotExist()
方法中的代码。
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)));
);
不确定这是否会成功编译和运行,因为我自己还没有运行过这段代码。希望它会解决您的问题。
【讨论】:
你好。谢谢你的回答。我在实施您的解决方案时遇到了麻烦。看到这个截图:i.imgur.com/Rp7IPr4.png @mnmncp firstonUserExistsCallback
应该是大写“O”而不是小写“o”。
你的接口名称也有小写的'o'开头
@mnmncp public void checkIfUserExists(OnUserExistsCallback onUserExistsCallback)
你没有包含需要的参数
对不起,那是我的错误。所以,我已经实现了解决方案,但在日志中得到了这个:hastebin.com/ulokigikog.scala【参考方案2】:
该行为是由于 checkUser.enqueue(new Callback<List<SavePlace>>()
的异步执行造成的。所以当你从checkIfUserExists()
调用这个方法时,你的执行线程不会等待checkUser.enqueue()
完成。相反,它将立即转到下一行并返回当前标志值为 false。 checkUser.enqueue()
将在后台线程中执行,您将在 onResponse()
方法中获得结果。根据您的代码,该行为是正确的。请尝试异步处理场景,因为这是网络调用的推荐方法。
【讨论】:
是的,我现在明白了。谢谢你。有没有你能想到的解决这个问题的办法?【参考方案3】:问题是你在调用这个方法的时候处理的是异步函数调用
uec.checkIfUserExists();
这个函数中的代码以正常方式执行,直到你在这里调用你的 api 的那一行
final Call<List<SavePlace>> checkUser = apiInterfaceSavePlace.getSavePlaces();
在后台线程中调用 web api 并且您的函数以正常方式执行并返回,这意味着您将获得标志为 false 值。 当后台任务完成后,里面的代码
public void onResponse()
方法被执行,这是一个回调方法,你得到你的值与 true 标志。
解决方案
您应该等待您的 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
);
【讨论】:
感谢您的回复。你能告诉我应该如何使用该接口在 checkIfUserExists() 或 enqueue 方法中调用 onCallBack 方法吗?以上是关于布尔标志始终为假的主要内容,如果未能解决你的问题,请参考以下文章