hello everyone i'm new here and new to android development, first i want to apologize if this was asked and answered before. i'm trying to build an android app and in the user profile i have 2 radio buttons for gender, male and female. i was able to pass the value of the selected radio button to the firebase database. this is the code i used:
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);
and this for the radio button selection
public void radioBtnGenderClick(View view) {
int radioBtnDogGenderId = radioGroupDogGender.getCheckedRadioButtonId();
radioBtnDogGender = (RadioButton) findViewById(radioBtnDogGenderId);
Toast.makeText(getBaseContext(),radioBtnDogGender.getText(),Toast.LENGTH_LONG).show();
}
i was able to pass back the value of the gender as text to the user profile screen
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);
}
when i go to the Edit User Profile the correct radio button is showen as checked, however when i click on Save Profile the app crashes like it did when no radio button was checked. if i reclick the same radio button in the edit profile page everything works ok.
how can i fix it so that the user won't have to reclick the radio button (unless he wants to change the selection) and that when saving the profile it will recognize the button as checked?
i think the issue is that when passing the radio button value to the database "radioBtnDogGender" is used and when passing back the value from the database the "radioBtmMale"/"radioBtnFemale" are used.
how can i pass the value into the "radioBtnDogGender" instead of the specific Male/Female radio buttons?
this is the xml code:
<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>
here is the stack trace when app crashes (pressing on save profile without reclicking the radio button):
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)
as i mentioned in the comments the Gender radio buttons works fine with the new code and when i tried to implement the same code to the Neutered radio buttons i got a new problem, the Neutered radio buttons stay empty and when i physically press on one of them the app restarts while leaving the Neutered radio buttons empty, in the View profile under Neutered it says "unspecified" here is the code for both the Gender and Neutered radio buttons
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();
}
}
did i forget anything or is a different code needed for the Neutered radio buttons?
To start with, in your onEvent
handler, you disregard the value of error
, which may lead to your crash as you try to access a potentially null
value for value
. The first line of your onEvent
handler should check if the listener has failed.
public void onEvent(@Nullable DocumentSnapshot value, @Nullable FirebaseFirestoreException error) {
if (error != null) {
// something has gone wrong, handle it
return;
}
// no errors, continue
// ...
}
The error could also come from the below lines:
String gender = value.getString("dogGender");
if (gender.equalsIgnoreCase("Male")){
radioBtnMale.setChecked(true);
} else if (gender.equalsIgnoreCase("Female")) {
radioBtnFemale.setChecked(true);
}
When your user loads up their profile for the first time, the value for dogGender
may be null
. When it is null
, you try to call null.equalsIgnoreCase(...)
which will throw a NullPointerException
. Instead, you should check if it's null
before comparing it to Female
and Male
. In addition, when changing the currently selected radio button programmatically, it won't call the radioBtnGenderClick
listener which means that radioBtnDogGender
doesn't get updated - so we update that here.
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;
}
While I've been typing this out, now that you've provided the stack trace for your error, we can actually see that the lines causing the error are:
public void radioBtnGenderClick(View view) {
int radioBtnDogGenderId = radioGroupDogGender.getCheckedRadioButtonId();
radioBtnDogGender = (RadioButton) findViewById(radioBtnDogGenderId);
Toast.makeText(getBaseContext(),radioBtnDogGender.getText(),Toast.LENGTH_LONG).show();
}
and
saveUserProfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ...
String dogGender = radioBtnDogGender.getText().toString();
// ...
}
}
As mentioned above, the radioBtnGenderClick
listener isn't called when you update the selected radio button using setChecked()
so radioGroupDogGender
could be null
until the user clicks one of the gender options unless you apply the changes above where you manually set radioBtnDogGender
. When the radioBtnGenderClick
listener is executed while there are no actively selected radio buttons in radioGroupDogGender
, radioGroupDogGender.getCheckedRadioButtonId()
returns a value of -1
. On the next line, you call findViewById(-1)
which then sets the value of radioBtnDogGender
to null
. Following that you effectively call ((RadioButton) null).getText()
which throws a 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();
}
}
Similarly, you also assume that radioBtnDogGender
is not null
in the onClickListener
of your saveUserProfile
button.
String dogGender = radioBtnDogGender != null ? radioBtnDogGender.getText().toString() : "Unspecified";
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.