开发者

What to save in Preference.onSaveInstanceState

开发者 https://www.devze.com 2023-03-16 14:14 出处:网络
I\'m creating a few custom preferences for an Android application. The two I\'m creating is a SeekBarPreference and a MultiSelectPreference.

I'm creating a few custom preferences for an Android application.

The two I'm creating is a SeekBarPreference and a MultiSelectPreference.

The SeekBarPreference is quite simple, it inherits from DialogPreference and has a custom content view in which it displays a SeekBar.

The MultiSelectPreference is a bit more advanced, it opens a Dialog when clicked which has a custom ListView and a button. When the button is pressed another Dialog is opened which has a generic ListView.

What should I save in onSaveInstanceState() for these preferences?

For the SeekBarPreference I assumed that I needed to save the value if isPersistant() is false and also the current slider progress (so I could restore) but after browsing the android source code doesn't seem like EditTextPreference cares about storing it's current text, only the saved value.

The DialogPreference does however save the current state of the dialog but it doesn't seem like that saves the state for its children, but it's quite hard to tell, I开发者_运维百科 got lost when I came to what a Window will do when onSaveInstanceState is called since it's abstract and I didn't find any subclasses.

Any insight to this problem would be greatly appreciated, my goal is to open source the code later so I want to do this right.


After a lot of testing and code browsing these are my conclusions:

  • You do not need to save the state of views if they are connected to a root view because they are saved when the root view gets saved, in my case that means I don't have to save the state of the SeekBar, that's handles when the dialog is saved by the super class.
  • You should always save your value if you aren't persistant
  • You should save all instance variables that change/can change after the preference is created, this means variables that can be changed with a setter or that can change over time.

Even though the last point is not followed by Google them selves they are wrong and an easy example shows why: Imagine you have a PreferenceActivity which contains two things; a ListPreference with 10 items and a generic preference that when pressed adds an item to the end of the ListPreference.

Now imagine that the user starts the application and presses the generic preference, the ListPreference now has 11 items. The user now opens the ListPreference.

If the application is closed and then killed the instance is saved, but the ListView only saves the stored value (if it isn't persistant), so when it reopens it only contains the initial 10 item.

Below is an example of a minimal app that displays the problem, just click on the button, open the list (there should be 4 items), close the app with the list open, kill the app from adb and reopen it, the list now has three items.

PreferenceTest.java

package com.example;

import java.util.ArrayList;
import java.util.Arrays;

import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;

public class PreferenceTest extends PreferenceActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);

        getPreferenceScreen().findPreference("button").setOnPreferenceClickListener(new OnPreferenceClickListener() {

            @Override
            public boolean onPreferenceClick(Preference preference) {
                ListPreference lp = (ListPreference) getPreferenceScreen().findPreference("list");

                ArrayList<CharSequence> al = new ArrayList<CharSequence>(Arrays.asList(lp.getEntries()));
                CharSequence items[] = new CharSequence[al.size()+1];
                al.add("Item " + items.length);
                lp.setEntries(al.toArray(items));

                al = new ArrayList<CharSequence>(Arrays.asList(lp.getEntryValues()));
                al.add("Value " + items.length);
                lp.setEntryValues(al.toArray(items));

                return true;
            }
        });
    }
}

res/xml/preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android">

  <ListPreference
    android:key="list"
    android:entries="@array/list_entries"
    android:entryValues="@array/list_values"
    android:title="Example list"
    android:summary="This list contains 3 items by default" />      

  <Preference
    android:key="button"
    android:title="Example button"
    android:summary="When clicked this adds an item to the list" />

</PreferenceScreen>

res/values/list_items.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="list_entries">
        <item>Item 1</item>
        <item>Item 2</item>
        <item>Item 3</item>
    </string-array>

    <string-array name="list_values">
        <item>Value 1</item>
        <item>Value 2</item>
        <item>Value 3</item>
    </string-array>
</resources>    
0

精彩评论

暂无评论...
验证码 换一张
取 消