What to save in Preference.onSaveInstanceState
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?
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>
精彩评论