0

I wrote my own number picker preference using android's brief guide and some googling. My question is regarding the onSaveInstanceState() method. On google's tutorial, it is suggested that we use the method isPersistent() to determine if the preference is persistent and if it is, then just return the superstate. I didn't do that because with this condition, if I swipe the number picker to a new number and then rotate the screen, the rotated version will return back to the persisted value. If I remove this condition then everything is ok. However, checking the source code of other preferences, like edittextpreference, this condition exists and the state is saved even if I change the value to an unsaved one and then rotate the screen.. Can somebody explain that please? Here is my code:

public class NumberPreference extends DialogPreference {
    private final static int DEFAULT_VALUE=R.integer.timer_def;
    private final static int DEFAULT_MIN_VALUE=R.integer.timer_min_def;
    private final static int DEFAULT_MAX_VALUE=R.integer.timer_max_def;
    private final int min;
    private final int max;
    private final String time;

    private int timer;
    private NumberPicker numberPicker;


    public NumberPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDialogLayoutResource(R.layout.number_preference);
        setNegativeButtonText("Cancel");
        setPositiveButtonText("OK");
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.number_preference, 0, 0);
        try{
            min=a.getInteger(R.styleable.number_preference_min, DEFAULT_MIN_VALUE);
            max=a.getInteger(R.styleable.number_preference_max, DEFAULT_MAX_VALUE);
            time=a.getString(R.styleable.number_preference_time);
        }finally{
            a.recycle();
        }
        setDialogIcon(null);
    }

    public void setSummary() {
        super.setSummary("Every "+getTimer()+' '+time);
    }

    @Override
    protected View onCreateView(ViewGroup parent) {
        setSummary();
        return super.onCreateView(parent);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            int number = numberPicker.getValue();
            if (callChangeListener(number)){
                timer=number;
                persistInt(timer);
                setSummary();
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return a.getInt(index,DEFAULT_VALUE);
    }

    @Override
    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
        if (restorePersistedValue) {
            timer = getPersistedInt(DEFAULT_VALUE);
        }
        else{
            timer =(Integer) defaultValue;
            persistInt(timer);
        }
    }

    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);
        numberPicker=(NumberPicker) view.findViewById(R.id.numpref_picker);
        numberPicker.setMinValue(min);
        numberPicker.setMaxValue(max);
        numberPicker.setValue(timer);

    }

    public int getTimer() {
        return getPersistedInt(DEFAULT_VALUE);
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        final Parcelable superState = super.onSaveInstanceState();
        if (isPersistent()) {
            return superState;
        }
        final SavedState myState=new SavedState(superState);
        if (numberPicker!= null) myState.value=numberPicker.getValue();
        return myState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state==null || !state.getClass().equals(SavedState.class)){
            super.onRestoreInstanceState(state);
            return;
        }
        SavedState myState=(SavedState)state;
        super.onRestoreInstanceState(myState.getSuperState());
        if (numberPicker!=null)numberPicker.setValue(myState.value);
    }

    private static class SavedState extends BaseSavedState {
        // field that holds the setting's value
        int value;

        public SavedState(Parcelable superState) {
            super(superState);
        }

        public SavedState(Parcel source) {
            super(source);
            // Get the current preference's value
            value = source.readInt();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            // Write the preference's value
            dest.writeInt(value);
        }

        // Standard creator object using an instance of this class
        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {

                    public SavedState createFromParcel(Parcel in) {
                        return new SavedState(in);
                    }

                    public SavedState[] newArray(int size) {
                        return new SavedState[size];
                    }
                };
    }

}

Thanks:)

michaelg9
  • 85
  • 2
  • 10

1 Answers1

0

without having tested it, would assume you might have to change

private final String time;

to

private String time;

and pass String.valueOf(time) as an argument into the .setSummary() method. of course, the occurrence in .onCreateView() would need to pass the value read from the preferences - or the default value as fallback, if nothing had been returned. try to make in more simple, than more complex.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • Hey syslogic, thanks for the answer. Maybe I didn't explain the problem really well. The string time is just a variable in the summary, it's not what concerns me. The problem is that if I have that condition and I click to open the number picker, then swipe to another number than the persistent one, and finally rotate the screen what I get is the number picker back to the persistent value. If I remove that condition, then the rotated number picker will be pointing on the value that I swapped before rotating – michaelg9 Jul 30 '16 at 22:20
  • @michaelg9 hope you got it working meanwhile with the discussion continued on G+... the `setSummary()` method should nevertheless be the only one thing one has to take care of manually (since it is ordinary not designated to display the value of a preference - even if often abused for that). – Martin Zeitler Aug 01 '16 at 02:09
  • @michaelg9 `onConfigurationChanged()` might also be relevant, to work against the the problem with the screen-orientation change. – Martin Zeitler Aug 01 '16 at 05:16