登录应用时出现奇怪的循环

huangapple go评论67阅读模式
英文:

strange loop when logging a user in to my app

问题

I've translated the code portions as you requested. Here they are:

我创建了一个简单的登录界面用于收集用户的电子邮件地址然后收集密码并加密它然后将这些数据发送到Firebase数据库并登录用户它会更改TextView和EditText以显示用户已登录并隐藏登录按钮一切都很顺利直到我添加了一个新的按钮来注销用户出于某种原因它会注销用户但立刻又自动登录用户有人可以快速查看一下代码看看我做错了什么谢谢

这是我的onClick方法

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.btn_login:
            geteditTexts();

            if (SIGNUP) {
                logUserIn();
            } else {
                sendUserDataToFirebase();
            }
            break;

        case R.id.btn_logout:
            setStatusLoggedOut();
            break;
    }
}

这个方法检查用户是否存在以及加密后的密码是否与数据库中存储的加密密钥匹配然后登录用户

private void logUserIn() {
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            if (snapshot.exists()) {
                userdata = snapshot.child("email").getValue(String.class);
                userpassword = snapshot.child("password").getValue(String.class);
                if (userpassword.matches(encryptedMsg) && userdata.matches(memail)) {
                    setStatusLoggedIn(snapshot);
                } else {
                    Toast.makeText(getBaseContext(), "Wrong email or password please try again", Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(getBaseContext(), "No account registered", Toast.LENGTH_SHORT).show();
            }
        }
    });
}

这个方法简单地将数据发送到Firebase

private void sendUserDataToFirebase() {
    reference.child("email").setValue(memail);
    reference.child("password").setValue(encryptedMsg);
}

我在onStart()中调用这个方法来检查用户是否已登录

private void checkUserLogin() {
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            signedin = snapshot.child("SIGNEDIN").getValue(Boolean.class);
            if (signedin) {
                setStatusLoggedIn(snapshot);
            } else {
                setStatusLoggedOut();
            }
        }
    });
}

最后这两个方法用于将用户标记为已登录或未登录

private void setStatusLoggedIn(DataSnapshot snapshot) {
    reference.child("SIGNEDIN").setValue(true);
    userdata = snapshot.child("email").getValue(String.class);
    et_email.setText(userdata);
    userpassword = snapshot.child("password").getValue(String.class);
    DecryptPassword();
    btn_login.setText("Already Signed in");
    btn_login.setOnClickListener(null);
    forgot_password.setVisibility(View.GONE);
    signup.setVisibility(View.GONE);
    tv_login_desc.setText("You Are Logged In");
    btn_signout.setVisibility(View.VISIBLE);
}

private void setStatusLoggedOut() {
    reference.child("SIGNEDIN").setValue(false);
    et_email.setText("");
    et_password.setText("");
    btn_login.setText("Login");
    btn_login.setOnClickListener(this);
    forgot_password.setVisibility(View.VISIBLE);
    signup.setVisibility(View.GONE);
    tv_login_desc.setText("Login");
    btn_signout.setVisibility(View.GONE);
}

If you have any specific questions or need further assistance with this code, please feel free to ask.

英文:

ive created a simple login screen that collects users email. then collects password and encrypts it. then sends that data to firebase database and signs the user in. it changes the textviews and edit texts to say the user is logged in and hides the login button. all works great. that is until i added a new button to log the user back out. for some reason it logs them out but instantly logs the user back in lol. can somebody just take a quick look at the code n see what ive done wrong. thanks.

this is my onClick method

  @Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_login:
geteditTexts();
if (SIGNUP) {
logUserIn();
} else {
sendUserDataToFirebase();
}
break;
case R.id.btn_logout:
setStatusLoggedOut();
break;

this method Checks the user exists and that the encrypted password matches the encrypted key stored with in that database then logs the user in

private void logUserIn() {
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
userdata = snapshot.child("email").getValue(String.class);
userpassword = snapshot.child("password").getValue(String.class);
if (userpassword.matches(encryptedMsg) & userdata.matches(memail)) {
setStatusLoggedIn(snapshot);
} else {
Toast.makeText(getBaseContext(), "Wrong email or password please try again", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getBaseContext(), "No account registered", Toast.LENGTH_SHORT).show();
}
}

this method simply sends the data to firebase

 private void sendUserDataToFirebase() {
reference.child("email").setValue(memail);
reference.child("password").setValue(encryptedMsg);
}

i call this method at onStart() to check if the user is logged in or not

private void checkUserLogin() {
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
signedin = snapshot.child("SIGNEDIN").getValue(Boolean.class);
if (signedin) {
setStatusLoggedIn(snapshot);
}else {
setStatusLoggedOut();
}
}

then finally these 2 methods set the user as logged in or out

  private void  setStatusLoggedIn(DataSnapshot snapshot){
reference.child("SIGNEDIN").setValue(true);
userdata = snapshot.child("email").getValue(String.class);
et_email.setText(userdata);
userpassword = snapshot.child("password").getValue(String.class);
DecryptPassword();
btn_login.setText("Already Signed in");
btn_login.setOnClickListener(null);
forgot_password.setVisibility(View.GONE);
signup.setVisibility(View.GONE);
tv_login_desc.setText("You Are Logged In ");
btn_signout.setVisibility(View.VISIBLE);
}
private void setStatusLoggedOut(){
reference.child("SIGNEDIN").setValue(false);
et_email.setText("");
et_password.setText("");
btn_login.setText("Login");
btn_login.setOnClickListener(this);
forgot_password.setVisibility(View.VISIBLE);
signup.setVisibility(View.GONE);
tv_login_desc.setText("Login");
btn_signout.setVisibility(View.GONE);
}

everything works ok when logging user in its

答案1

得分: 3

如果所有你分享的代码片段中的 reference 变量指向相同的数据库路径,那么循环的原因可以解释。

首先,你在这里在 reference 上添加了一个永久的监听器:

reference.addValueEventListener(new ValueEventListener() {
    ...

然后,当该监听器触发时,你调用了 setStatusLoggedIn,然后将数据写入 reference

reference.child("SIGNEDIN").setValue(true);

这将再次触发第一个代码片段中的值事件监听器,它将再次写入数据库,触发监听器,依此类推...

如果你只想从数据库中读取一次数据,可以使用 addListenerForSingleValueEvent 或根据一次性读取数据文档中显示的 getData 方法。

英文:

If the reference variable in all the code snippets you shared points to the same database path, then the loop can be explained.

First up, you are adding a permanent listener on reference here:

reference.addValueEventListener(new ValueEventListener() {
...

Then when that listener is trigger, you call setStatusLoggedIn which then writes to reference:

reference.child("SIGNEDIN").setValue(true);

This will then trigger the value event listener from the first snippet again, which will then once again write to the database, which triggers the listener again, etc...

If you only want to read from the database once, use addListenerForSingleValueEvent or getData as shown in the documentation on reading data once.

huangapple
  • 本文由 发表于 2023年2月7日 01:52:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75364862.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定