【问题标题】: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

这意味着它检测到了电子邮件并设置了共享首选项 但标志仍然是假的。

【问题讨论】:

    标签: android retrofit2 android-sharedpreferences


    【解决方案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 方法吗?
    猜你喜欢
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多