向Firebase Database提交UserData时重复创建大量节点的问题
问题描述
使用Firebase Auth实现邮箱密码认证,同时向Firebase Database提交用户数据时,点击一次提交按钮会生成大量重复的用户节点,需求是用户注册时创建带有唯一Push ID的新用户节点,运行过程无报错。
UserRegistration.java 代码
public class UserRegistration extends AppCompatActivity { EditText name, school, address, standard, contact, password, conf_password, email; Button submit; String regex = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+(?:\\.[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+)*@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$"; ProgressDialog progressDialog; FirebaseAuth mAuth; FirebaseUser mUser; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_student_registration); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); name = findViewById(R.id.name); standard = findViewById(R.id.standard); school = findViewById(R.id.school); address = findViewById(R.id.address); contact = findViewById(R.id.contact); email = findViewById(R.id.email); password = findViewById(R.id.password); conf_password = findViewById(R.id.conf_password); submit = findViewById(R.id.registration_button); progressDialog = new ProgressDialog(this); mAuth = FirebaseAuth.getInstance(); mUser = mAuth.getCurrentUser(); submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { PerformAuth(); } }); } private void PerformAuth() { String input_name = name.getText().toString(); String input_standard = standard.getText().toString(); String input_school = school.getText().toString(); String input_address = address.getText().toString(); String input_contact = contact.getText().toString(); String input_email = email.getText().toString(); String input_password = password.getText().toString(); String input_conf_password = conf_password.getText().toString(); if(input_name.isEmpty()){ name.requestFocus(); name.setError("Enter Your Name"); } else if (input_standard.isEmpty()) { standard.requestFocus(); standard.setError("Enter Your Class"); } else if (input_school.isEmpty()) { school.setError("Enter Name of Your School"); school.requestFocus(); } else if (input_address.isEmpty()) { address.requestFocus(); address.setError("Enter your Address"); } else if (!input_email.matches(regex)) { email.requestFocus(); email.setError("Enter Valid Email"); } else if (input_password.isEmpty() || input_password.length()<6) { password.requestFocus(); password.setError("Enter Valid Password (length must be greater than 6)"); } else if (!input_password.equals(input_conf_password)) { conf_password.requestFocus(); conf_password.setError("Password not matched"); } else if (input_contact.isEmpty() || input_contact.length()>10) { contact.requestFocus(); contact.setError("Enter valid Contact Number"); } else { progressDialog.setMessage("Please wait while Registering..."); progressDialog.setTitle("Registration"); progressDialog.setCanceledOnTouchOutside(false); progressDialog.show(); UserDetails userDetails = new UserDetails(input_name,input_standard,input_school,input_address,input_email,input_password,input_contact); DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("User"); databaseReference.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { databaseReference.push().setValue(userDetails); } @Override public void onCancelled(@NonNull DatabaseError error) {} }); mAuth.createUserWithEmailAndPassword(input_email,input_password).addOnCompleteListener(new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()){ progressDialog.dismiss(); SendUserToNextActivity(); Toast.makeText(UserRegistration.this, "Registration Successful", Toast.LENGTH_SHORT).show(); }else { progressDialog.dismiss(); Toast.makeText(UserRegistration.this, ""+task.getException(), Toast.LENGTH_SHORT).show(); } } }); } } private void SendUserToNextActivity() { Intent intent = new Intent(UserRegistration.this,User_Login.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }
UserDetails.java 代码
package com.gov.thecoachinginstitute; public class UserDetails { String Name,Standard,School,Address,Email,Password,Contact; public UserDetails(String name, String standard, String school, String address, String email, String password, String contact) { Name = name; Standard = standard; School = school; Address = address; Email = email; Password = password; Contact = contact; } public String getName() { return Name; } public String getStandard() { return Standard; } public String getSchool() { return School; } public String getAddress() { return Address; } public String getEmail() { return Email; } public String getPassword() { return Password; } public String getContact() { return Contact; } }
问题截图


解决方案
问题根源
代码中使用addValueEventListener监听User节点的数据变化,每次调用push().setValue(userDetails)写入新数据后,会触发onDataChange回调,导致重复执行写入操作,循环往复生成大量重复节点。此外,当前逻辑在Auth创建用户之前就写入数据库,可能出现Auth失败但数据已写入的异常情况。
修正步骤
- 移除不必要的
ValueEventListener,直接调用push().setValue()写入数据; - 将数据库写入逻辑移至Auth创建用户成功的回调中,确保只有Auth成功后才保存用户数据。
修正后的PerformAuth方法代码
private void PerformAuth() { String input_name = name.getText().toString(); String input_standard = standard.getText().toString(); String input_school = school.getText().toString(); String input_address = address.getText().toString(); String input_contact = contact.getText().toString(); String input_email = email.getText().toString(); String input_password = password.getText().toString(); String input_conf_password = conf_password.getText().toString(); if(input_name.isEmpty()){ name.requestFocus(); name.setError("Enter Your Name"); } else if (input_standard.isEmpty()) { standard.requestFocus(); standard.setError("Enter Your Class"); } else if (input_school.isEmpty()) { school.setError("Enter Name of Your School"); school.requestFocus(); } else if (input_address.isEmpty()) { address.requestFocus(); address.setError("Enter your Address"); } else if (!input_email.matches(regex)) { email.requestFocus(); email.setError("Enter Valid Email"); } else if (input_password.isEmpty() || input_password.length()<6) { password.requestFocus(); password.setError("Enter Valid Password (length must be greater than 6)"); } else if (!input_password.equals(input_conf_password)) { conf_password.requestFocus(); conf_password.setError("Password not matched"); } else if (input_contact.isEmpty() || input_contact.length()>10) { contact.requestFocus(); contact.setError("Enter valid Contact Number"); } else { progressDialog.setMessage("Please wait while Registering..."); progressDialog.setTitle("Registration"); progressDialog.setCanceledOnTouchOutside(false); progressDialog.show(); UserDetails userDetails = new UserDetails(input_name,input_standard,input_school,input_address,input_email,input_password,input_contact); DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("User"); mAuth.createUserWithEmailAndPassword(input_email,input_password).addOnCompleteListener(new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()){ // Auth成功后再写入数据库 databaseReference.push().setValue(userDetails); progressDialog.dismiss(); SendUserToNextActivity(); Toast.makeText(UserRegistration.this, "Registration Successful", Toast.LENGTH_SHORT).show(); }else { progressDialog.dismiss(); Toast.makeText(UserRegistration.this, ""+task.getException(), Toast.LENGTH_SHORT).show(); } } }); } }
额外优化建议
- 不建议在数据库中存储明文密码,Firebase Auth已经负责密码管理,无需重复存储;
- 可以使用Firebase Auth生成的用户UID作为数据库节点键,替代Push ID,更便于关联用户与数据:
// 替换push()为用户UID String userId = mAuth.getCurrentUser().getUid(); databaseReference.child(userId).setValue(userDetails);
内容的提问来源于stack exchange,提问作者Dhananjay Singh
相关产品推荐
相关产品推荐

