英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论