布尔标志始终为假

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 first onUserExistsCallback 应该是大写“O”而不是小写“o”。 你的接口名称也有小写的'o'开头 @mnmncp public void checkIfUserExists(OnUserExistsCallback onUserExistsCallback)你没有包含需要的参数 对不起,那是我的错误。所以,我已经实现了解决方案,但在日志中得到了这个:hastebin.com/ulokigikog.scala【参考方案2】:

该行为是由于 checkUser.enqueue(new Callback&lt;List&lt;SavePlace&gt;&gt;() 的异步执行造成的。所以当你从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 方法吗?

以上是关于布尔标志始终为假的主要内容,如果未能解决你的问题,请参考以下文章

当应该为真时,Android Studio 改造响应返回布尔值为假

什么是布尔变量,要如何使用?

为啥当值为假时我不能传递过滤数据(它是布尔值)

C ++打印布尔值,显示什么? [关闭]

将布尔值设置为假是多余的吗?

布尔列表检查列表中的每个项目是不是为假