如何从firebase数据库android中检索单选按钮的值



大家好,我是新手,也是android开发的新手。首先,我想道歉,如果这是问和回答之前。我试图建立一个安卓应用程序,并在用户配置文件我有性别,男性和女性2个单选按钮。我能够将选中的单选按钮的值传递给firebase数据库。这是我使用的代码:

saveUserProfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String dogBirthdate = displayDogBirthday.getText().toString();
String dogGender = radioBtnDogGender.getText().toString();
String dogNeutered = radioBtnNeutered.getText().toString();
String aboutTheDog = aboutDog.getText().toString();
progressBar.setVisibility(View.VISIBLE);
//userId = fireAuth.getCurrentUser().getUid();
documentReference = fireStore.collection("users").document(userId);
Map<String, Object> user = new HashMap<>();
user.put("dogBirthdate", dogBirthdate);
user.put("dogGender", dogGender);
user.put("dogNeutered", dogNeutered);
user.put("aboutDog", aboutTheDog);

和这个用于单选按钮选择

public void radioBtnGenderClick(View view) {
int radioBtnDogGenderId = radioGroupDogGender.getCheckedRadioButtonId();
radioBtnDogGender = (RadioButton) findViewById(radioBtnDogGenderId);
Toast.makeText(getBaseContext(),radioBtnDogGender.getText(),Toast.LENGTH_LONG).show();
}

我能够将性别的值作为文本传递回用户配置文件屏幕

userId = fireAuth.getCurrentUser().getUid();
documentReference = fireStore.collection("users").document(userId);
documentReference.addSnapshotListener(new EventListener<DocumentSnapshot>() {
@Override
public void onEvent(@Nullable DocumentSnapshot value, @Nullable FirebaseFirestoreException error) {
dogName.setText(value.getString("dogName"));
aboutDog.setText(value.getString("aboutDog"));
displayDogBirthday.setText(value.getString("dogBirthdate"));
String gender = value.getString("dogGender");
if (gender.equalsIgnoreCase("Male")){
radioBtnMale.setChecked(true);

}else if (gender.equalsIgnoreCase("Female")){
radioBtnFemale.setChecked(true);
}

当我去编辑用户配置文件时,正确的单选按钮显示为选中,但是当我点击保存配置文件时,应用程序崩溃,就像没有选中单选按钮一样。如果我在编辑配置文件页面中重新单击相同的单选按钮,一切都可以正常工作。

我该如何修复它,以便用户不必重新单击单选按钮(除非他想改变选择),并且在保存配置文件时将识别按钮作为检查?

我认为问题是,当传递单选按钮值到数据库"radioBtnDogGender",当从数据库传回值时,使用"radioBtmMale"/"radioBtnFemale"使用。

如何将值传递给"radioBtnDogGender"而不是特定的男/女单选按钮?

这是XML代码:

<RadioGroup
android:id="@+id/radioGroupDogGender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.488"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.459">
<RadioButton
android:id="@+id/radioBtnMale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="radioBtnGenderClick"
android:text="Male" />
<RadioButton
android:id="@+id/radioBtnFemale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="radioBtnGenderClick"
android:text="Female" />
</RadioGroup>

下面是应用程序崩溃时的堆栈跟踪(按下保存配置文件而不重新单击单选按钮):

2021-03-11 14:54:59.303 13459-13459/com.example.loginandregfirebase E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.loginandregfirebase, PID: 13459
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence android.widget.RadioButton.getText()' on a null object reference
at com.example.loginandregfirebase.EditUserProfilePage$7.onClick(EditUserProfilePage.java:205)
at android.view.View.performClick(View.java:7448)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

正如我在评论中提到的,性别单选按钮与新代码一起工作很好,当我试图对阉割的单选按钮实施相同的代码时,我遇到了一个新问题,阉割的单选按钮保持空,当我物理按下其中一个时,应用程序重新启动,同时留下阉割的单选按钮空,在阉割下的视图配置文件中它说"未指定";这里是性别和阉割单选按钮的代码

radioGroupDogGender.clearCheck();
radioGroupNeutered.clearCheck();
String gender = value.getString("dogGender");
if (gender == null || gender.equalsIgnoreCase("Unspecified gender")){
// gender unknown, leave unselected
radioGroupDogGender = null;
}else
if (gender.equalsIgnoreCase("Male")){
radioBtnMale.setChecked(true);
radioBtnDogGender = radioBtnMale;

}else if (gender.equalsIgnoreCase("Female")){
radioBtnFemale.setChecked(true);
radioBtnDogGender = radioBtnFemale;
}
String neutered = value.getString("dogNeutered");
if (neutered == null || neutered.equalsIgnoreCase("Unspecified")){
// neutered unknown, leave unselected
radioGroupNeutered = null;
}else
if (neutered.equalsIgnoreCase("Yes")){
radioBtnNeuteredYes.setChecked(true);
radioBtnNeutered = radioBtnNeuteredYes;
}else if (neutered.equalsIgnoreCase("No")){
radioBtnNeuteredNo.setChecked(true);
radioBtnNeutered = radioBtnNeuteredNo;
}


saveUserProfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String dogBirthdate = displayDogBirthday.getText().toString();
String dogGender = radioBtnDogGender != null ? radioBtnDogGender.getText().toString():"unspecified gender";
//String dogGender = radioBtnDogGender.getText().toString();
String dogNeutered = radioBtnNeutered != null ? radioBtnNeutered.getText().toString(): "unspecified";
//String dogNeutered = radioBtnNeutered.getText().toString();
String aboutTheDog = aboutDog.getText().toString();
progressBar.setVisibility(View.VISIBLE);
//userId = fireAuth.getCurrentUser().getUid();
documentReference = fireStore.collection("users").document(userId);
Map<String, Object> user = new HashMap<>();
user.put("dogBirthdate", dogBirthdate);
user.put("dogGender", dogGender);
user.put("dogNeutered", dogNeutered);
user.put("aboutDog", aboutTheDog);

public void radioBtnGenderClick(View view) {
int radioBtnDogGenderId = radioGroupDogGender.getCheckedRadioButtonId();
if (radioBtnDogGenderId == -1){
//gender deselected
Toast.makeText(getBaseContext(),"gender deselected", Toast.LENGTH_LONG).show();
}else {
radioBtnDogGender = (RadioButton) findViewById(radioBtnDogGenderId);
Toast.makeText(getBaseContext(), radioBtnDogGender.getText(), Toast.LENGTH_LONG).show();
}
}
public void radioBtnNeutered(View view) {
int radioBtnNeuteredId = radioGroupNeutered.getCheckedRadioButtonId();
if (radioBtnNeuteredId == -1){
Toast.makeText(getBaseContext(),"neutered deselected",Toast.LENGTH_LONG).show();
}else {
radioBtnNeutered = (RadioButton) findViewById(radioBtnNeuteredId);
Toast.makeText(getBaseContext(), radioBtnNeutered.getText(), Toast.LENGTH_LONG).show();
}
}

我忘记了什么,还是需要一个不同的代码为阉割单选按钮?

首先,在您的onEvent处理程序中,您忽略了error的值,这可能会导致您在尝试访问value的潜在null值时崩溃。onEvent处理程序的第一行应该检查侦听器是否失败。

public void onEvent(@Nullable DocumentSnapshot value, @Nullable FirebaseFirestoreException error) {
if (error != null) {
// something has gone wrong, handle it
return;
}
// no errors, continue
// ...
}

错误也可能来自以下行:

String gender = value.getString("dogGender");
if (gender.equalsIgnoreCase("Male")){
radioBtnMale.setChecked(true);
} else if (gender.equalsIgnoreCase("Female")) {
radioBtnFemale.setChecked(true);
}

当用户第一次加载配置文件时,dogGender的值可能是null。当它是null时,您尝试调用null.equalsIgnoreCase(...),这将抛出NullPointerException。相反,您应该在将其与FemaleMale进行比较之前检查它是否为null。此外,当以编程方式改变当前选择的单选按钮时,它不会调用radioBtnGenderClick侦听器,这意味着radioBtnDogGender不会被更新-所以我们在这里更新。

radioGroupDogGender.clearCheck();
String gender = value.getString("dogGender");
if (gender == null || gender.equalsIgnoreCase("Unspecified")) {
// gender unknown, leave unselected
radioBtnDogGender = null;
} else if (gender.equalsIgnoreCase("Male")) {
radioBtnMale.setChecked(true);
radioBtnDogGender = radioBtnMale;
} else if (gender.equalsIgnoreCase("Female")) {
radioBtnFemale.setChecked(true);
radioBtnDogGender = radioBtnFemale;
}

当我输入这些代码时,现在您已经为错误提供了堆栈跟踪,我们可以看到导致错误的行是:

public void radioBtnGenderClick(View view) {
int radioBtnDogGenderId = radioGroupDogGender.getCheckedRadioButtonId();
radioBtnDogGender = (RadioButton) findViewById(radioBtnDogGenderId);
Toast.makeText(getBaseContext(),radioBtnDogGender.getText(),Toast.LENGTH_LONG).show();
}

saveUserProfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ...
String dogGender = radioBtnDogGender.getText().toString();
// ...
}
}

如上所述,当您使用setChecked()更新所选的单选按钮时,radioBtnGenderClick侦听器不会被调用,因此radioGroupDogGender可以是null,直到用户单击其中一个性别选项,除非您应用上述手动设置radioBtnDogGender的更改。当radioBtnGenderClick侦听器被执行,而radioGroupDogGender中没有主动选择的单选按钮时,radioGroupDogGender.getCheckedRadioButtonId()返回-1的值。在下一行,调用findViewById(-1),然后将radioBtnDogGender的值设置为null。在此之后,你有效地调用((RadioButton) null).getText(),它抛出一个NullPointerException.

public void radioBtnGenderClick(View view) {
int radioBtnDogGenderId = radioGroupDogGender.getCheckedRadioButtonId();
if (radioBtnDogGenderId == -1) {
// gender deselected
Toast.makeText(getBaseContext(),"Gender deselected",Toast.LENGTH_LONG).show();
} else {
radioBtnDogGender = (RadioButton) findViewById(radioBtnDogGenderId);
Toast.makeText(getBaseContext(),radioBtnDogGender.getText(),Toast.LENGTH_LONG).show();
}
}

同样,您还假设radioBtnDogGender不是saveUserProfile按钮的onClickListener中的null

String dogGender = radioBtnDogGender != null ? radioBtnDogGender.getText().toString() : "Unspecified";

最新更新