Search code examples
javaandroidandroid-radiogrouponsaveinstancestate

save radiogroup onSavedInstance


i have a problem with saving radiogroup status when screen rotates.
I have two independent radiogroups with 2 radiobuttons for every radiogroup. I try to use get, getCheckedRadioButtonId but it doesn't work at all.

What i am doing wrong and how to save radiougroup checked radiobutton properly ? Thanks in advance!

EDIT:

xml:

     <RadioGroup
            android:id="@+id/radio_result_group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintBottom_toBottomOf="@+id/textView"
            app:layout_constraintEnd_toEndOf="@+id/convert_to3"
            app:layout_constraintTop_toTopOf="@+id/textView">

            <RadioButton
                android:id="@+id/metric_sys_result"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:padding="4dp"
                android:text="@string/metric_sys"
                android:textSize="14sp" />

            <RadioButton
                android:id="@+id/imperial_sys_result"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="4dp"

                android:layout_weight="1"
                android:padding="4dp"
                android:text="@string/imperial_sys"
                android:textColorLink="@color/colorAccent"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="@+id/measurementView" />
        </RadioGroup>
<RadioGroup
        android:id="@+id/radio_value_gropu"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="@+id/measurementView"
        app:layout_constraintEnd_toEndOf="@+id/convert_from5"
        app:layout_constraintTop_toTopOf="@+id/measurementView">

        <RadioButton
            android:id="@+id/metric_sys_value"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:padding="4dp"
            android:text="@string/metric_sys"
            android:textSize="14sp" />

        <RadioButton
            android:id="@+id/imperial_sys_value"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"

            android:layout_weight="1"
            android:padding="4dp"
            android:text="@string/imperial_sys"
            android:textColorLink="@color/colorAccent"
            android:textSize="14sp"
            app:layout_constraintBottom_toBottomOf="@+id/measurementView" />
    </RadioGroup>

//java code

    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.RadioGroup;
    import android.widget.Spinner;
    import android.widget.SpinnerAdapter;
    import android.widget.TextView;
    import android.widget.Toast;

    import butterknife.BindView;
    import butterknife.ButterKnife;
    import butterknife.OnClick;


    public class MainActivity extends AppCompatActivity  {
        protected double getEnteredValue;
        protected SpinnerAdapter checkAdapter;
        protected int pos;
   protected ArrayAdapter<String> adapter 1, adapter2, adapter3,
                adapter4;


        @BindView(R.id.unit_From_spinner)Spinner spinnerFrom;
        @BindView(R.id.unit_To_spinner)Spinner spinnertTo;
         @BindView(R.id.radio_result_group) RadioGroup resultGroup;
        @BindView(R.id.radio_value_gropu) RadioGroup valueGroup;
       @BindView(R.id.valueEditTextView) EditText valueEdit;
      @BindView(R.id.resultView) TextView resultView;
        @BindView(R.id.conver_button) Button  convertButton;

        @Override
        public void onSaveInstanceState(Bundle savedInstanceState) {
            savedInstanceState.putString("result",resultView.getText().toString());
            savedInstanceState.putString("value",valueEdit.getText().toString());
            savedInstanceState.putInt("from",spinnerFrom.getSelectedItemPosition()); // get selected item from spinner 1
            savedInstanceState.putInt("to",spinnertTo.getSelectedItemPosition());
            savedInstanceState.putInt("radGroup1", resultGroup.getCheckedRadioButtonId());
            savedInstanceState.putInt("radGroup2", valueGroup.getCheckedRadioButtonId());
            super.onSaveInstanceState(savedInstanceState);
        }


            @Override
        protected void onCreate(Bundle savedInstanceState)  {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.unifiedlayout);
            ButterKnife.bind(this);
            convertButton.setEnabled(false);
        adapter1 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray( R.array.adapter_1) );
    adapter2 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray(R.array. adapter_2));
    adapter3 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray( R.array. adapter_3) );
    adapter4 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray(R.array. adapter_4));


        }

        @Override
        public void onRestoreInstanceState(Bundle savedInstanceState) {
            resultView.setText(savedInstanceState.getString("result"));
            valueEdit.setText(savedInstanceState.getString("value"));
            spinnerFrom.setSelection(savedInstanceState.getInt("from"));
            spinnertTo.setSelection(savedInstanceState.getInt("to"));

    //?
            super.onSaveInstanceState(savedInstanceState);
        }

    @OnClick({R.id.button1, R.id.button2,R.id.button3,R.id.button4
           } )
    public void setViewOnClickEvent(View view){
        switch(view.getId()){
            case R.id.mass_button:
                            fillSpinner(adapter1, adapter2); // fill spinner with values
                break;
            case R.id.speed_button:
                fillSpinner(adapter3,
                        adapter4);
                break;
       }
    }

protected void fillSpinner (final ArrayAdapter<String> spinnerToAdapter,
                                final ArrayAdapter<String> spinnerFromAdapter){

        valueGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup valueGroup, int checkedId) {
                pos = valueGroup.indexOfChild(findViewById(checkedId));
                switch (pos) {
                    case 0:
                        spinnerFrom.setAdapter(spinnerToAdapter);
                        break;
                    case 1:
                        spinnerFrom.setAdapter(spinnerFromAdapter);
                        break;
                }
            }
        });
        resultGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup resultGroup, int checkedId) {
                pos = resultGroup.indexOfChild(findViewById(checkedId));
                switch (pos) {
                    case 0:
                        spinnertTo.setAdapter(spinnerToAdapter);
                        break;
                    case 1:
                        spinnertTo.setAdapter(spinnerFromAdapter);
                        break;
                }
            }
        });
    }

Solution

  • You already save the id of the checked RadioButtons like this:

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //
        // saving other values...
        //
        outState.putInt("radGroup1", resultGroup.getCheckedRadioButtonId());
        outState.putInt("radGroup2", valueGroup.getCheckedRadioButtonId());
        Log.d(TAG, "onSaveInstanceState: result id " + resultGroup.getCheckedRadioButtonId() + ", value id = " + valueGroup.getCheckedRadioButtonId());
        super.onSaveInstanceState(outState);
    }
    

    So you can retrieve the saved values either in onCreate() (note: only if(savedInstanceState != null) ) or in onRestoreInstanceState(). The second method will only be called if savedInstanceState is not null.

    private int checkedResultButtonsId;
    private int checkedValueButtonsId;
    
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        checkedResultButtonsId = savedInstanceState.getInt("radGroup1");
        checkedValueButtonsId = savedInstanceState.getInt("radGroup2");
        Log.d(TAG, "onRestoreInstanceState: result id " + checkedResultButtonsId + ", value id = " + checkedValueButtonsId);
    }
    

    Normally you do not need to set the checked state of a RadioButton manually after a configuration change. My sample app (just plain android, no data binding) keeps the state of the RadioButtons automatically, so I'm not sure why you need to save the id's like you do. Your question sounds like the RadioGroup loses its state on rotation.

    (Maybe you just do not call super.onRestoreInstanceState()? At least it is missing in your MainActivity code snippet )

    So I tried to simulate this effect by resetting all RadioButtons to unchecked after the call to super.onRestoreInstanceState() and restored the state by using the saved values:

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        resetRadioButtons(resultGroup);
        resetRadioButtons(valueGroup);
    
        checkedResultButtonsId = savedInstanceState.getInt("radGroup1");
        checkedValueButtonsId = savedInstanceState.getInt("radGroup2");
    
        // if saved values are > 0: set checked state to 'true'
        if(checkedResultButtonsId > 0){
            ((RadioButton)resultGroup.findViewById(checkedResultButtonsId)).setChecked(true);
        }
        if(checkedResultButtonsId > 0){
            ((RadioButton)valueGroup.findViewById(checkedValueButtonsId)).setChecked(true);
        }
    }
    

    The result was a bit weird: the restored RadioButtons seemed to be stuck in an unchecked state and only recovered after checking their sibling RadioButton.

    I guess my code snippet somehow interfered with the workings of super.onRestoreInstanceState(). So I moved the problematic parts to onStart():

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        checkedResultButtonsId = savedInstanceState.getInt("radGroup1");
        checkedValueButtonsId = savedInstanceState.getInt("radGroup2");
    }
    

    Note: resetRadioButtons() is my just way of ensuring that there is something to restore: uncheck every RadioButton in the RadioGroup.

    @Override
    protected void onStart() {
        super.onStart();
        resetRadioButtons(resultGroup);
        resetRadioButtons(valueGroup);
    
        if(checkedResultButtonsId > 0){
            ((RadioButton)resultGroup.findViewById(checkedResultButtonsId)).setChecked(true);
        }
        if(checkedResultButtonsId > 0){
            ((RadioButton)valueGroup.findViewById(checkedValueButtonsId)).setChecked(true);
        }
    }
    

    This worked nicely, so I hope it's helpful for you as well.