简体   繁体   中英

how to retrieve value of a radio button back from firebase database android

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM