summaryrefslogtreecommitdiffstats
path: root/core/java/android/preference/Preference.java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch)
tree35051494d2af230dce54d6b31c6af8fc24091316 /core/java/android/preference/Preference.java
downloadframeworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.zip
frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.gz
frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.bz2
Initial Contribution
Diffstat (limited to 'core/java/android/preference/Preference.java')
-rw-r--r--core/java/android/preference/Preference.java1577
1 files changed, 1577 insertions, 0 deletions
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
new file mode 100644
index 0000000..1db7525
--- /dev/null
+++ b/core/java/android/preference/Preference.java
@@ -0,0 +1,1577 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import com.android.internal.util.CharSequences;
+import android.view.AbsSavedState;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+import android.widget.TextView;
+
+/**
+ * The {@link Preference} class represents the basic preference UI building
+ * block that is displayed by a {@link PreferenceActivity} in the form of a
+ * {@link ListView}. This class provides the {@link View} to be displayed in
+ * the activity and associates with a {@link SharedPreferences} to
+ * store/retrieve the preference data.
+ * <p>
+ * When specifying a preference hierarchy in XML, each tag name can point to a
+ * subclass of {@link Preference}, similar to the view hierarchy and layouts.
+ * <p>
+ * This class contains a {@code key} that will be used as the key into the
+ * {@link SharedPreferences}. It is up to the subclass to decide how to store
+ * the value.
+ *
+ * @attr ref android.R.styleable#Preference_key
+ * @attr ref android.R.styleable#Preference_title
+ * @attr ref android.R.styleable#Preference_summary
+ * @attr ref android.R.styleable#Preference_order
+ * @attr ref android.R.styleable#Preference_layout
+ * @attr ref android.R.styleable#Preference_widgetLayout
+ * @attr ref android.R.styleable#Preference_enabled
+ * @attr ref android.R.styleable#Preference_selectable
+ * @attr ref android.R.styleable#Preference_dependency
+ * @attr ref android.R.styleable#Preference_persistent
+ * @attr ref android.R.styleable#Preference_defaultValue
+ * @attr ref android.R.styleable#Preference_shouldDisableView
+ */
+public class Preference implements Comparable<Preference>, OnDependencyChangeListener {
+ /**
+ * Specify for {@link #setOrder(int)} if a specific order is not required.
+ */
+ public static final int DEFAULT_ORDER = Integer.MAX_VALUE;
+
+ private Context mContext;
+ private PreferenceManager mPreferenceManager;
+
+ /**
+ * Set when added to hierarchy since we need a unique ID within that
+ * hierarchy.
+ */
+ private long mId;
+
+ private OnPreferenceChangeListener mOnChangeListener;
+ private OnPreferenceClickListener mOnClickListener;
+
+ private int mOrder = DEFAULT_ORDER;
+ private CharSequence mTitle;
+ private CharSequence mSummary;
+ private String mKey;
+ private Intent mIntent;
+ private boolean mEnabled = true;
+ private boolean mSelectable = true;
+ private boolean mRequiresKey;
+ private boolean mPersistent = true;
+ private String mDependencyKey;
+ private Object mDefaultValue;
+
+ /**
+ * @see #setShouldDisableView(boolean)
+ */
+ private boolean mShouldDisableView = true;
+
+ private int mLayoutResId = com.android.internal.R.layout.preference;
+ private int mWidgetLayoutResId;
+ private boolean mHasSpecifiedLayout = false;
+
+ private OnPreferenceChangeInternalListener mListener;
+
+ private List<Preference> mDependents;
+
+ private boolean mBaseMethodCalled;
+
+ /**
+ * Interface definition for a callback to be invoked when this
+ * {@link Preference Preference's} value has been changed by the user and is
+ * about to be set and/or persisted. This gives the client a chance
+ * to prevent setting and/or persisting the value.
+ */
+ public interface OnPreferenceChangeListener {
+ /**
+ * Called when this preference has been changed by the user. This is
+ * called before the preference's state is about to be updated and
+ * before the state is persisted.
+ *
+ * @param preference This preference.
+ * @param newValue The new value of the preference.
+ * @return Whether or not to update this preference's state with the new value.
+ */
+ boolean onPreferenceChange(Preference preference, Object newValue);
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when a preference is
+ * clicked.
+ */
+ public interface OnPreferenceClickListener {
+ /**
+ * Called when a preference has been clicked.
+ *
+ * @param preference The preference that was clicked.
+ * @return Whether the click was handled.
+ */
+ boolean onPreferenceClick(Preference preference);
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when this
+ * {@link Preference} is changed or if this is a group, there is an
+ * addition/removal of {@link Preference}(s). This is used internally.
+ */
+ interface OnPreferenceChangeInternalListener {
+ /**
+ * Called when this preference has changed.
+ *
+ * @param preference This preference.
+ */
+ void onPreferenceChange(Preference preference);
+
+ /**
+ * Called when this group has added/removed {@link Preference}(s).
+ *
+ * @param preference This preference.
+ */
+ void onPreferenceHierarchyChange(Preference preference);
+ }
+
+ /**
+ * Perform inflation from XML and apply a class-specific base style. This
+ * constructor of {@link Preference} allows subclasses to use their own base
+ * style when they are inflating. For example, a {@link CheckBoxPreference}'s
+ * constructor would call this version of the super class constructor and
+ * supply {@code android.R.attr.checkBoxPreferenceStyle} for <var>defStyle</var>;
+ * this allows the theme's checkbox preference style to modify all of the base
+ * preference attributes as well as the {@link CheckBoxPreference} class's
+ * attributes.
+ *
+ * @param context The Context this is associated with, through which it can
+ * access the current theme, resources, {@link SharedPreferences},
+ * etc.
+ * @param attrs The attributes of the XML tag that is inflating the preference.
+ * @param defStyle The default style to apply to this preference. If 0, no style
+ * will be applied (beyond what is included in the theme). This
+ * may either be an attribute resource, whose value will be
+ * retrieved from the current theme, or an explicit style
+ * resource.
+ * @see #Preference(Context, AttributeSet)
+ */
+ public Preference(Context context, AttributeSet attrs, int defStyle) {
+ mContext = context;
+
+ TypedArray a = context.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.Preference);
+ if (a.hasValue(com.android.internal.R.styleable.Preference_layout) ||
+ a.hasValue(com.android.internal.R.styleable.Preference_widgetLayout)) {
+ // This preference has a custom layout defined (not one taken from
+ // the default style)
+ mHasSpecifiedLayout = true;
+ }
+ a.recycle();
+
+ a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Preference,
+ defStyle, 0);
+ for (int i = a.getIndexCount(); i >= 0; i--) {
+ int attr = a.getIndex(i);
+ switch (attr) {
+ case com.android.internal.R.styleable.Preference_key:
+ mKey = a.getString(attr);
+ break;
+
+ case com.android.internal.R.styleable.Preference_title:
+ mTitle = a.getString(attr);
+ break;
+
+ case com.android.internal.R.styleable.Preference_summary:
+ mSummary = a.getString(attr);
+ break;
+
+ case com.android.internal.R.styleable.Preference_order:
+ mOrder = a.getInt(attr, mOrder);
+ break;
+
+ case com.android.internal.R.styleable.Preference_layout:
+ mLayoutResId = a.getResourceId(attr, mLayoutResId);
+ break;
+
+ case com.android.internal.R.styleable.Preference_widgetLayout:
+ mWidgetLayoutResId = a.getResourceId(attr, mWidgetLayoutResId);
+ break;
+
+ case com.android.internal.R.styleable.Preference_enabled:
+ mEnabled = a.getBoolean(attr, true);
+ break;
+
+ case com.android.internal.R.styleable.Preference_selectable:
+ mSelectable = a.getBoolean(attr, true);
+ break;
+
+ case com.android.internal.R.styleable.Preference_persistent:
+ mPersistent = a.getBoolean(attr, mPersistent);
+ break;
+
+ case com.android.internal.R.styleable.Preference_dependency:
+ mDependencyKey = a.getString(attr);
+ break;
+
+ case com.android.internal.R.styleable.Preference_defaultValue:
+ mDefaultValue = onGetDefaultValue(a, attr);
+ break;
+
+ case com.android.internal.R.styleable.Preference_shouldDisableView:
+ mShouldDisableView = a.getBoolean(attr, mShouldDisableView);
+ break;
+ }
+ }
+ a.recycle();
+ }
+
+ /**
+ * Constructor that is called when inflating a preference from XML. This is
+ * called when a preference is being constructed from an XML file, supplying
+ * attributes that were specified in the XML file. This version uses a
+ * default style of 0, so the only attribute values applied are those in the
+ * Context's Theme and the given AttributeSet.
+ *
+ * @param context The Context this is associated with, through which it can
+ * access the current theme, resources, {@link SharedPreferences},
+ * etc.
+ * @param attrs The attributes of the XML tag that is inflating the
+ * preference.
+ * @see #Preference(Context, AttributeSet, int)
+ */
+ public Preference(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ /**
+ * Constructor to create a Preference.
+ *
+ * @param context The context to store preference values.
+ */
+ public Preference(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Called when {@link Preference} is being inflated and the default value
+ * attribute needs to be read. Since different preference types have
+ * different value types, the subclass should get and return the default
+ * value which will be its value type.
+ * <p>
+ * For example, if the value type is String, the body of the method would
+ * proxy to {@link TypedArray#getString(int)}.
+ *
+ * @param a The set of attributes.
+ * @param index The index of the default value attribute.
+ * @return The default value of this preference type.
+ */
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return null;
+ }
+
+ /**
+ * Sets an {@link Intent} to be used for
+ * {@link Context#startActivity(Intent)} when the preference is clicked.
+ *
+ * @param intent The intent associated with the preference.
+ */
+ public void setIntent(Intent intent) {
+ mIntent = intent;
+ }
+
+ /**
+ * Return the {@link Intent} associated with this preference.
+ *
+ * @return The {@link Intent} last set via {@link #setIntent(Intent)} or XML.
+ */
+ public Intent getIntent() {
+ return mIntent;
+ }
+
+ /**
+ * Sets the layout resource that is inflated as the {@link View} to be shown
+ * for this preference. In most cases, the default layout is sufficient for
+ * custom preferences and only the widget layout needs to be changed.
+ * <p>
+ * This layout should contain a {@link ViewGroup} with ID
+ * {@link android.R.id#widget_frame} to be the parent of the specific widget
+ * for this preference. It should similarly contain
+ * {@link android.R.id#title} and {@link android.R.id#summary}.
+ *
+ * @param layoutResId The layout resource ID to be inflated and returned as
+ * a {@link View}.
+ * @see #setWidgetLayoutResource(int)
+ */
+ public void setLayoutResource(int layoutResId) {
+
+ if (!mHasSpecifiedLayout) {
+ mHasSpecifiedLayout = true;
+ }
+
+ mLayoutResId = layoutResId;
+ }
+
+ /**
+ * Gets the layout resource that will be shown as the {@link View} for this preference.
+ *
+ * @return The layout resource ID.
+ */
+ public int getLayoutResource() {
+ return mLayoutResId;
+ }
+
+ /**
+ * Sets The layout for the controllable widget portion of a preference. This
+ * is inflated into the main layout. For example, a checkbox preference
+ * would specify a custom layout (consisting of just the CheckBox) here,
+ * instead of creating its own main layout.
+ *
+ * @param widgetLayoutResId The layout resource ID to be inflated into the
+ * main layout.
+ * @see #setLayoutResource(int)
+ */
+ public void setWidgetLayoutResource(int widgetLayoutResId) {
+ mWidgetLayoutResId = widgetLayoutResId;
+ }
+
+ /**
+ * Gets the layout resource for the controllable widget portion of a preference.
+ *
+ * @return The layout resource ID.
+ */
+ public int getWidgetLayoutResource() {
+ return mWidgetLayoutResId;
+ }
+
+ /**
+ * Gets the View that will be shown in the {@link PreferenceActivity}.
+ *
+ * @param convertView The old view to reuse, if possible. Note: You should
+ * check that this view is non-null and of an appropriate type
+ * before using. If it is not possible to convert this view to
+ * display the correct data, this method can create a new view.
+ * @param parent The parent that this view will eventually be attached to.
+ * @return Returns the same Preference object, for chaining multiple calls
+ * into a single statement.
+ * @see #onCreateView(ViewGroup)
+ * @see #onBindView(View)
+ */
+ public View getView(View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = onCreateView(parent);
+ }
+ onBindView(convertView);
+ return convertView;
+ }
+
+ /**
+ * Creates the View to be shown for this preference in the
+ * {@link PreferenceActivity}. The default behavior is to inflate the main
+ * layout of this preference (see {@link #setLayoutResource(int)}. If
+ * changing this behavior, please specify a {@link ViewGroup} with ID
+ * {@link android.R.id#widget_frame}.
+ * <p>
+ * Make sure to call through to the superclass's implementation.
+ *
+ * @param parent The parent that this view will eventually be attached to.
+ * @return The View that displays this preference.
+ * @see #onBindView(View)
+ */
+ protected View onCreateView(ViewGroup parent) {
+ final LayoutInflater layoutInflater =
+ (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ final View layout = layoutInflater.inflate(mLayoutResId, parent, false);
+
+ if (mWidgetLayoutResId != 0) {
+ final ViewGroup widgetFrame = (ViewGroup)layout.findViewById(com.android.internal.R.id.widget_frame);
+ layoutInflater.inflate(mWidgetLayoutResId, widgetFrame);
+ }
+
+ return layout;
+ }
+
+ /**
+ * Binds the created View to the data for the preference.
+ * <p>
+ * This is a good place to grab references to custom Views in the layout and
+ * set properties on them.
+ * <p>
+ * Make sure to call through to the superclass's implementation.
+ *
+ * @param view The View that shows this preference.
+ * @see #onCreateView(ViewGroup)
+ */
+ protected void onBindView(View view) {
+ TextView textView = (TextView) view.findViewById(com.android.internal.R.id.title);
+ if (textView != null) {
+ textView.setText(getTitle());
+ }
+
+ textView = (TextView) view.findViewById(com.android.internal.R.id.summary);
+ if (textView != null) {
+ final CharSequence summary = getSummary();
+ if (!TextUtils.isEmpty(summary)) {
+ if (textView.getVisibility() != View.VISIBLE) {
+ textView.setVisibility(View.VISIBLE);
+ }
+
+ textView.setText(getSummary());
+ } else {
+ if (textView.getVisibility() != View.GONE) {
+ textView.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ if (mShouldDisableView) {
+ setEnabledStateOnViews(view, mEnabled);
+ }
+ }
+
+ /**
+ * Makes sure the view (and any children) get the enabled state changed.
+ */
+ private void setEnabledStateOnViews(View v, boolean enabled) {
+ v.setEnabled(enabled);
+
+ if (v instanceof ViewGroup) {
+ final ViewGroup vg = (ViewGroup) v;
+ for (int i = vg.getChildCount() - 1; i >= 0; i--) {
+ setEnabledStateOnViews(vg.getChildAt(i), enabled);
+ }
+ }
+ }
+
+ /**
+ * Sets the order of this {@link Preference} with respect to other
+ * {@link Preference} on the same level. If this is not specified, the
+ * default behavior is to sort alphabetically. The
+ * {@link PreferenceGroup#setOrderingAsAdded(boolean)} can be used to order
+ * preferences based on the order they appear in the XML.
+ *
+ * @param order The order for this preference. A lower value will be shown
+ * first. Use {@link #DEFAULT_ORDER} to sort alphabetically or
+ * allow ordering from XML.
+ * @see PreferenceGroup#setOrderingAsAdded(boolean)
+ * @see #DEFAULT_ORDER
+ */
+ public void setOrder(int order) {
+ if (order != mOrder) {
+ mOrder = order;
+
+ // Reorder the list
+ notifyHierarchyChanged();
+ }
+ }
+
+ /**
+ * Gets the order of this {@link Preference}.
+ *
+ * @return The order of this {@link Preference}.
+ * @see #setOrder(int)
+ */
+ public int getOrder() {
+ return mOrder;
+ }
+
+ /**
+ * Sets the title for the preference. This title will be placed into the ID
+ * {@link android.R.id#title} within the View created by
+ * {@link #onCreateView(ViewGroup)}.
+ *
+ * @param title The title of the preference.
+ */
+ public void setTitle(CharSequence title) {
+ if (title == null && mTitle != null || title != null && !title.equals(mTitle)) {
+ mTitle = title;
+ notifyChanged();
+ }
+ }
+
+ /**
+ * @see #setTitle(CharSequence)
+ * @param titleResId The title as a resource ID.
+ */
+ public void setTitle(int titleResId) {
+ setTitle(mContext.getString(titleResId));
+ }
+
+ /**
+ * Returns the title of the preference.
+ *
+ * @return The title.
+ * @see #setTitle(CharSequence)
+ */
+ public CharSequence getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * Returns the summary of the preference.
+ *
+ * @return The summary.
+ * @see #setSummary(CharSequence)
+ */
+ public CharSequence getSummary() {
+ return mSummary;
+ }
+
+ /**
+ * Sets the summary for the preference. This summary will be placed into the
+ * ID {@link android.R.id#summary} within the View created by
+ * {@link #onCreateView(ViewGroup)}.
+ *
+ * @param summary The summary of the preference.
+ */
+ public void setSummary(CharSequence summary) {
+ if (summary == null && mSummary != null || summary != null && !summary.equals(mSummary)) {
+ mSummary = summary;
+ notifyChanged();
+ }
+ }
+
+ /**
+ * @see #setSummary(CharSequence)
+ * @param summaryResId The summary as a resource.
+ */
+ public void setSummary(int summaryResId) {
+ setSummary(mContext.getString(summaryResId));
+ }
+
+ /**
+ * Sets whether this preference is enabled. If disabled, the preference will
+ * not handle clicks.
+ *
+ * @param enabled Whether the preference is enabled.
+ */
+ public void setEnabled(boolean enabled) {
+ if (mEnabled != enabled) {
+ mEnabled = enabled;
+
+ // Enabled state can change dependent preferences' states, so notify
+ notifyDependencyChange(shouldDisableDependents());
+
+ notifyChanged();
+ }
+ }
+
+ /**
+ * Whether this {@link Preference} should be enabled in the list.
+ *
+ * @return Whether this preference is enabled.
+ */
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ /**
+ * Sets whether this preference is selectable.
+ *
+ * @param selectable Whether the preference is selectable.
+ */
+ public void setSelectable(boolean selectable) {
+ if (mSelectable != selectable) {
+ mSelectable = selectable;
+ notifyChanged();
+ }
+ }
+
+ /**
+ * Whether this {@link Preference} should be selectable in the list.
+ *
+ * @return Whether this preference is selectable.
+ */
+ public boolean isSelectable() {
+ return mSelectable;
+ }
+
+ /**
+ * Sets whether this {@link Preference} should disable its view when it gets
+ * disabled.
+ * <p>
+ * For example, set this and {@link #setEnabled(boolean)} to false for
+ * preferences that are only displaying information and 1) should not be
+ * clickable 2) should not have the view set to the disabled state.
+ *
+ * @param shouldDisableView Whether this preference should disable its view
+ * when the preference is disabled.
+ */
+ public void setShouldDisableView(boolean shouldDisableView) {
+ mShouldDisableView = shouldDisableView;
+ notifyChanged();
+ }
+
+ /**
+ * @see #setShouldDisableView(boolean)
+ * @return Whether this preference should disable its view when it is disabled.
+ */
+ public boolean getShouldDisableView() {
+ return mShouldDisableView;
+ }
+
+ /**
+ * Returns a unique ID for this preference. This ID should be unique across all
+ * preferences in a hierarchy.
+ *
+ * @return A unique ID for this preference.
+ */
+ long getId() {
+ return mId;
+ }
+
+ /**
+ * Processes a click on the preference. This includes saving the value to
+ * the {@link SharedPreferences}. However, the overridden method should
+ * call {@link #callChangeListener(Object)} to make sure the client wants to
+ * update the preference's state with the new value.
+ */
+ protected void onClick() {
+ }
+
+ /**
+ * Sets the key for the preference which is used as a key to the
+ * {@link SharedPreferences}. This should be unique for the package.
+ *
+ * @param key The key for the preference.
+ * @see #getId()
+ */
+ public void setKey(String key) {
+ mKey = key;
+
+ if (mRequiresKey && !hasKey()) {
+ requireKey();
+ }
+ }
+
+ /**
+ * Gets the key for the preference, which is also the key used for storing
+ * values into SharedPreferences.
+ *
+ * @return The key.
+ */
+ public String getKey() {
+ return mKey;
+ }
+
+ /**
+ * Checks whether the key is present, and if it isn't throws an
+ * exception. This should be called by subclasses that store preferences in
+ * the {@link SharedPreferences}.
+ */
+ void requireKey() {
+ if (mKey == null) {
+ throw new IllegalStateException("Preference does not have a key assigned.");
+ }
+
+ mRequiresKey = true;
+ }
+
+ /**
+ * Returns whether this {@link Preference} has a valid key.
+ *
+ * @return Whether the key exists and is not a blank string.
+ */
+ public boolean hasKey() {
+ return !TextUtils.isEmpty(mKey);
+ }
+
+ /**
+ * Returns whether this {@link Preference} is persistent. If it is persistent, it stores its value(s) into
+ * the persistent {@link SharedPreferences} storage.
+ *
+ * @return Whether this is persistent.
+ */
+ public boolean isPersistent() {
+ return mPersistent;
+ }
+
+ /**
+ * Convenience method of whether at the given time this method is called,
+ * the {@link Preference} should store/restore its value(s) into the
+ * {@link SharedPreferences}. This, at minimum, checks whether the
+ * {@link Preference} is persistent and it currently has a key. Before you
+ * save/restore from the {@link SharedPreferences}, check this first.
+ *
+ * @return Whether to persist the value.
+ */
+ protected boolean shouldPersist() {
+ return mPreferenceManager != null && isPersistent() && hasKey();
+ }
+
+ /**
+ * Sets whether this {@link Preference} is persistent. If it is persistent,
+ * it stores its value(s) into the persistent {@link SharedPreferences}
+ * storage.
+ *
+ * @param persistent Whether it should store its value(s) into the {@link SharedPreferences}.
+ */
+ public void setPersistent(boolean persistent) {
+ mPersistent = persistent;
+ }
+
+ /**
+ * Call this method after the user changes the preference, but before the
+ * internal state is set. This allows the client to ignore the user value.
+ *
+ * @param newValue The new value of the preference.
+ * @return Whether or not the user value should be set as the preference
+ * value (and persisted).
+ */
+ protected boolean callChangeListener(Object newValue) {
+ return mOnChangeListener == null ? true : mOnChangeListener.onPreferenceChange(this, newValue);
+ }
+
+ /**
+ * Sets the callback to be invoked when this preference is changed by the
+ * user (but before the internal state has been updated).
+ *
+ * @param onPreferenceChangeListener The callback to be invoked.
+ */
+ public void setOnPreferenceChangeListener(OnPreferenceChangeListener onPreferenceChangeListener) {
+ mOnChangeListener = onPreferenceChangeListener;
+ }
+
+ /**
+ * Gets the callback to be invoked when this preference is changed by the
+ * user (but before the internal state has been updated).
+ *
+ * @return The callback to be invoked.
+ */
+ public OnPreferenceChangeListener getOnPreferenceChangeListener() {
+ return mOnChangeListener;
+ }
+
+ /**
+ * Sets the callback to be invoked when this preference is clicked.
+ *
+ * @param onPreferenceClickListener The callback to be invoked.
+ */
+ public void setOnPreferenceClickListener(OnPreferenceClickListener onPreferenceClickListener) {
+ mOnClickListener = onPreferenceClickListener;
+ }
+
+ /**
+ * Gets the callback to be invoked when this preference is clicked.
+ *
+ * @return The callback to be invoked.
+ */
+ public OnPreferenceClickListener getOnPreferenceClickListener() {
+ return mOnClickListener;
+ }
+
+ /**
+ * Called when a click should be performed.
+ *
+ * @param preferenceScreen Optional {@link PreferenceScreen} whose hierarchy click
+ * listener should be called in the proper order (between other
+ * processing).
+ */
+ void performClick(PreferenceScreen preferenceScreen) {
+
+ if (!isEnabled()) {
+ return;
+ }
+
+ onClick();
+
+ if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) {
+ return;
+ }
+
+ PreferenceManager preferenceManager = getPreferenceManager();
+ if (preferenceManager != null) {
+ PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager
+ .getOnPreferenceTreeClickListener();
+ if (preferenceScreen != null && listener != null
+ && listener.onPreferenceTreeClick(preferenceScreen, this)) {
+ return;
+ }
+ }
+
+ if (mIntent != null) {
+ Context context = getContext();
+ context.startActivity(mIntent);
+ }
+ }
+
+ /**
+ * Returns the context of this preference. Each preference in a preference hierarchy can be
+ * from different context (for example, if multiple activities provide preferences into a single
+ * {@link PreferenceActivity}). This context will be used to save the preference valus.
+ *
+ * @return The context of this preference.
+ */
+ public Context getContext() {
+ return mContext;
+ }
+
+ /**
+ * Returns the {@link SharedPreferences} where this preference can read its
+ * value(s). Usually, it's easier to use one of the helper read methods:
+ * {@link #getPersistedBoolean(boolean)}, {@link #getPersistedFloat(float)},
+ * {@link #getPersistedInt(int)}, {@link #getPersistedLong(long)},
+ * {@link #getPersistedString(String)}. To save values, see
+ * {@link #getEditor()}.
+ * <p>
+ * In some cases, writes to the {@link #getEditor()} will not be committed
+ * right away and hence not show up in the returned
+ * {@link SharedPreferences}, this is intended behavior to improve
+ * performance.
+ *
+ * @return The {@link SharedPreferences} where this preference reads its
+ * value(s), or null if it isn't attached to a preference hierarchy.
+ * @see #getEditor()
+ */
+ public SharedPreferences getSharedPreferences() {
+ if (mPreferenceManager == null) {
+ return null;
+ }
+
+ return mPreferenceManager.getSharedPreferences();
+ }
+
+ /**
+ * Returns an {@link SharedPreferences.Editor} where this preference can
+ * save its value(s). Usually it's easier to use one of the helper save
+ * methods: {@link #persistBoolean(boolean)}, {@link #persistFloat(float)},
+ * {@link #persistInt(int)}, {@link #persistLong(long)},
+ * {@link #persistString(String)}. To read values, see
+ * {@link #getSharedPreferences()}. If {@link #shouldCommit()} returns
+ * true, it is this Preference's responsibility to commit.
+ * <p>
+ * In some cases, writes to this will not be committed right away and hence
+ * not show up in the shared preferences, this is intended behavior to
+ * improve performance.
+ *
+ * @return A {@link SharedPreferences.Editor} where this preference saves
+ * its value(s), or null if it isn't attached to a preference
+ * hierarchy.
+ * @see #shouldCommit()
+ * @see #getSharedPreferences()
+ */
+ public SharedPreferences.Editor getEditor() {
+ if (mPreferenceManager == null) {
+ return null;
+ }
+
+ return mPreferenceManager.getEditor();
+ }
+
+ /**
+ * Returns whether the {@link Preference} should commit its saved value(s) in
+ * {@link #getEditor()}. This may return false in situations where batch
+ * committing is being done (by the manager) to improve performance.
+ *
+ * @return Whether the Preference should commit its saved value(s).
+ * @see #getEditor()
+ */
+ public boolean shouldCommit() {
+ if (mPreferenceManager == null) {
+ return false;
+ }
+
+ return mPreferenceManager.shouldCommit();
+ }
+
+ /**
+ * Compares preferences based on order (if set), otherwise alphabetically on title.
+ * <p>
+ * {@inheritDoc}
+ */
+ public int compareTo(Preference another) {
+ if (mOrder != DEFAULT_ORDER
+ || (mOrder == DEFAULT_ORDER && another.mOrder != DEFAULT_ORDER)) {
+ // Do order comparison
+ return mOrder - another.mOrder;
+ } else if (mTitle == null) {
+ return 1;
+ } else if (another.mTitle == null) {
+ return -1;
+ } else {
+ // Do name comparison
+ return CharSequences.compareToIgnoreCase(mTitle, another.mTitle);
+ }
+ }
+
+ /**
+ * Sets the internal change listener.
+ *
+ * @param listener The listener.
+ * @see #notifyChanged()
+ */
+ final void setOnPreferenceChangeInternalListener(OnPreferenceChangeInternalListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Should be called when the data of this {@link Preference} has changed.
+ */
+ protected void notifyChanged() {
+ if (mListener != null) {
+ mListener.onPreferenceChange(this);
+ }
+ }
+
+ /**
+ * Should be called this is a group a {@link Preference} has been
+ * added/removed from this group, or the ordering should be
+ * re-evaluated.
+ */
+ protected void notifyHierarchyChanged() {
+ if (mListener != null) {
+ mListener.onPreferenceHierarchyChange(this);
+ }
+ }
+
+ /**
+ * Gets the {@link PreferenceManager} that manages this preference's tree.
+ *
+ * @return The {@link PreferenceManager}.
+ */
+ public PreferenceManager getPreferenceManager() {
+ return mPreferenceManager;
+ }
+
+ /**
+ * Called when this preference has been attached to a preference hierarchy.
+ * Make sure to call the super implementation.
+ *
+ * @param preferenceManager The preference manager of the hierarchy.
+ */
+ protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
+ mPreferenceManager = preferenceManager;
+
+ mId = preferenceManager.getNextId();
+
+ dispatchSetInitialValue();
+ }
+
+ /**
+ * Called when the preference hierarchy has been attached to the
+ * {@link PreferenceActivity}. This can also be called when this
+ * {@link Preference} has been attached to a group that was already attached
+ * to the {@link PreferenceActivity}.
+ */
+ protected void onAttachedToActivity() {
+ // At this point, the hierarchy that this preference is in is connected
+ // with all other preferences.
+ registerDependency();
+ }
+
+ private void registerDependency() {
+
+ if (TextUtils.isEmpty(mDependencyKey)) return;
+
+ Preference preference = findPreferenceInHierarchy(mDependencyKey);
+ if (preference != null) {
+ preference.registerDependent(this);
+ } else {
+ throw new IllegalStateException("Dependency \"" + mDependencyKey
+ + "\" not found for preference \"" + mKey + "\" (title: \"" + mTitle + "\"");
+ }
+ }
+
+ private void unregisterDependency() {
+ if (mDependencyKey != null) {
+ final Preference oldDependency = findPreferenceInHierarchy(mDependencyKey);
+ if (oldDependency != null) {
+ oldDependency.unregisterDependent(this);
+ }
+ }
+ }
+
+ /**
+ * Find a Preference in this hierarchy (the whole thing,
+ * even above/below your {@link PreferenceScreen} screen break) with the given
+ * key.
+ * <p>
+ * This only functions after we have been attached to a hierarchy.
+ *
+ * @param key The key of the {@link Preference} to find.
+ * @return The {@link Preference} object of a preference
+ * with the given key.
+ */
+ protected Preference findPreferenceInHierarchy(String key) {
+ if (TextUtils.isEmpty(key) || mPreferenceManager == null) {
+ return null;
+ }
+
+ return mPreferenceManager.findPreference(key);
+ }
+
+ /**
+ * Adds a dependent Preference on this preference so we can notify it.
+ * Usually, the dependent preference registers itself (it's good for it to
+ * know it depends on something), so please use
+ * {@link Preference#setDependency(String)} on the dependent preference.
+ *
+ * @param dependent The dependent Preference that will be enabled/disabled
+ * according to the state of this preference.
+ */
+ private void registerDependent(Preference dependent) {
+ if (mDependents == null) {
+ mDependents = new ArrayList<Preference>();
+ }
+
+ mDependents.add(dependent);
+
+ dependent.onDependencyChanged(this, shouldDisableDependents());
+ }
+
+ /**
+ * Removes a dependent Preference on this preference.
+ *
+ * @param dependent The dependent Preference that will be enabled/disabled
+ * according to the state of this preference.
+ * @return Returns the same Preference object, for chaining multiple calls
+ * into a single statement.
+ */
+ private void unregisterDependent(Preference dependent) {
+ if (mDependents != null) {
+ mDependents.remove(dependent);
+ }
+ }
+
+ /**
+ * Notifies any listening dependents of a change that affects the
+ * dependency.
+ *
+ * @param disableDependents Whether this {@link Preference} should disable
+ * its dependents.
+ */
+ public void notifyDependencyChange(boolean disableDependents) {
+ final List<Preference> dependents = mDependents;
+
+ if (dependents == null) {
+ return;
+ }
+
+ final int dependentsCount = dependents.size();
+ for (int i = 0; i < dependentsCount; i++) {
+ dependents.get(i).onDependencyChanged(this, disableDependents);
+ }
+ }
+
+ /**
+ * Called when the dependency changes.
+ *
+ * @param dependency The preference that this preference depends on.
+ * @param disableDependent Whether to disable this preference.
+ */
+ public void onDependencyChanged(Preference dependency, boolean disableDependent) {
+ setEnabled(!disableDependent);
+ }
+
+ /**
+ * Should return whether this preference's dependents should currently be
+ * disabled.
+ *
+ * @return True if the dependents should be disabled, otherwise false.
+ */
+ public boolean shouldDisableDependents() {
+ return !isEnabled();
+ }
+
+ /**
+ * Sets the key of a Preference that this Preference will depend on. If that
+ * Preference is not set or is off, this Preference will be disabled.
+ *
+ * @param dependencyKey The key of the Preference that this depends on.
+ */
+ public void setDependency(String dependencyKey) {
+ // Unregister the old dependency, if we had one
+ unregisterDependency();
+
+ // Register the new
+ mDependencyKey = dependencyKey;
+ registerDependency();
+ }
+
+ /**
+ * Returns the key of the dependency on this preference.
+ *
+ * @return The key of the dependency.
+ * @see #setDependency(String)
+ */
+ public String getDependency() {
+ return mDependencyKey;
+ }
+
+ /**
+ * Called when this Preference is being removed from the hierarchy. You
+ * should remove any references to this Preference that you know about. Make
+ * sure to call through to the superclass implementation.
+ */
+ protected void onPrepareForRemoval() {
+ unregisterDependency();
+ }
+
+ /**
+ * Sets the default value for the preference, which will be set either if
+ * persistence is off or persistence is on and the preference is not found
+ * in the persistent storage.
+ *
+ * @param defaultValue The default value.
+ */
+ public void setDefaultValue(Object defaultValue) {
+ mDefaultValue = defaultValue;
+ }
+
+ private void dispatchSetInitialValue() {
+ // By now, we know if we are persistent.
+ final boolean shouldPersist = shouldPersist();
+ if (!shouldPersist || !getSharedPreferences().contains(mKey)) {
+ if (mDefaultValue != null) {
+ onSetInitialValue(false, mDefaultValue);
+ }
+ } else {
+ onSetInitialValue(true, null);
+ }
+ }
+
+ /**
+ * Implement this to set the initial value of the Preference. If the
+ * restoreValue flag is true, you should restore the value from the shared
+ * preferences. If false, you should set (and possibly store to shared
+ * preferences if {@link #shouldPersist()}) to defaultValue.
+ * <p>
+ * This may not always be called. One example is if it should not persist
+ * but there is no default value given.
+ *
+ * @param restorePersistedValue Whether to restore the persisted value
+ * (true), or use the given default value (false).
+ * @param defaultValue The default value. Only use if restoreValue is false.
+ */
+ protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
+ }
+
+ private void tryCommit(SharedPreferences.Editor editor) {
+ if (mPreferenceManager.shouldCommit()) {
+ editor.commit();
+ }
+ }
+
+ /**
+ * Attempts to persist a String to the SharedPreferences.
+ * <p>
+ * This will check if the Preference is persistent, get an editor from
+ * the preference manager, put the string, check if we should commit (and
+ * commit if so).
+ *
+ * @param value The value to persist.
+ * @return Whether the Preference is persistent. (This is not whether the
+ * value was persisted, since we may not necessarily commit if there
+ * will be a batch commit later.)
+ * @see #getPersistedString(String)
+ */
+ protected boolean persistString(String value) {
+ if (shouldPersist()) {
+ // Shouldn't store null
+ if (value == getPersistedString(null)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+ editor.putString(mKey, value);
+ tryCommit(editor);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to get a persisted String from the SharedPreferences.
+ * <p>
+ * This will check if the Preference is persistent, get the shared
+ * preferences from the preference manager, get the value.
+ *
+ * @param defaultReturnValue The default value to return if either the
+ * Preference is not persistent or the Preference is not in the
+ * shared preferences.
+ * @return The value from the shared preferences or the default return
+ * value.
+ * @see #persistString(String)
+ */
+ protected String getPersistedString(String defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return mPreferenceManager.getSharedPreferences().getString(mKey, defaultReturnValue);
+ }
+
+ /**
+ * Attempts to persist an int to the SharedPreferences.
+ *
+ * @param value The value to persist.
+ * @return Whether the Preference is persistent. (This is not whether the
+ * value was persisted, since we may not necessarily commit if there
+ * will be a batch commit later.)
+ * @see #persistString(String)
+ * @see #getPersistedInt(int)
+ */
+ protected boolean persistInt(int value) {
+ if (shouldPersist()) {
+ if (value == getPersistedInt(~value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+ editor.putInt(mKey, value);
+ tryCommit(editor);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to get a persisted int from the SharedPreferences.
+ *
+ * @param defaultReturnValue The default value to return if either the
+ * Preference is not persistent or the Preference is not in the
+ * shared preferences.
+ * @return The value from the shared preferences or the default return
+ * value.
+ * @see #getPersistedString(String)
+ * @see #persistInt(int)
+ */
+ protected int getPersistedInt(int defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return mPreferenceManager.getSharedPreferences().getInt(mKey, defaultReturnValue);
+ }
+
+ /**
+ * Attempts to persist a float to the SharedPreferences.
+ *
+ * @param value The value to persist.
+ * @return Whether the Preference is persistent. (This is not whether the
+ * value was persisted, since we may not necessarily commit if there
+ * will be a batch commit later.)
+ * @see #persistString(String)
+ * @see #getPersistedFloat(float)
+ */
+ protected boolean persistFloat(float value) {
+ if (shouldPersist()) {
+ if (value == getPersistedFloat(Float.NaN)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+ editor.putFloat(mKey, value);
+ tryCommit(editor);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to get a persisted float from the SharedPreferences.
+ *
+ * @param defaultReturnValue The default value to return if either the
+ * Preference is not persistent or the Preference is not in the
+ * shared preferences.
+ * @return The value from the shared preferences or the default return
+ * value.
+ * @see #getPersistedString(String)
+ * @see #persistFloat(float)
+ */
+ protected float getPersistedFloat(float defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return mPreferenceManager.getSharedPreferences().getFloat(mKey, defaultReturnValue);
+ }
+
+ /**
+ * Attempts to persist a long to the SharedPreferences.
+ *
+ * @param value The value to persist.
+ * @return Whether the Preference is persistent. (This is not whether the
+ * value was persisted, since we may not necessarily commit if there
+ * will be a batch commit later.)
+ * @see #persistString(String)
+ * @see #getPersistedLong(long)
+ */
+ protected boolean persistLong(long value) {
+ if (shouldPersist()) {
+ if (value == getPersistedLong(~value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+ editor.putLong(mKey, value);
+ tryCommit(editor);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to get a persisted long from the SharedPreferences.
+ *
+ * @param defaultReturnValue The default value to return if either the
+ * Preference is not persistent or the Preference is not in the
+ * shared preferences.
+ * @return The value from the shared preferences or the default return
+ * value.
+ * @see #getPersistedString(String)
+ * @see #persistLong(long)
+ */
+ protected long getPersistedLong(long defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return mPreferenceManager.getSharedPreferences().getLong(mKey, defaultReturnValue);
+ }
+
+ /**
+ * Attempts to persist a boolean to the SharedPreferences.
+ *
+ * @param value The value to persist.
+ * @return Whether the Preference is persistent. (This is not whether the
+ * value was persisted, since we may not necessarily commit if there
+ * will be a batch commit later.)
+ * @see #persistString(String)
+ * @see #getPersistedBoolean(boolean)
+ */
+ protected boolean persistBoolean(boolean value) {
+ if (shouldPersist()) {
+ if (value == getPersistedBoolean(!value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+ editor.putBoolean(mKey, value);
+ tryCommit(editor);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to get a persisted boolean from the SharedPreferences.
+ *
+ * @param defaultReturnValue The default value to return if either the
+ * Preference is not persistent or the Preference is not in the
+ * shared preferences.
+ * @return The value from the shared preferences or the default return
+ * value.
+ * @see #getPersistedString(String)
+ * @see #persistBoolean(boolean)
+ */
+ protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return mPreferenceManager.getSharedPreferences().getBoolean(mKey, defaultReturnValue);
+ }
+
+ boolean hasSpecifiedLayout() {
+ return mHasSpecifiedLayout;
+ }
+
+ @Override
+ public String toString() {
+ return getFilterableStringBuilder().toString();
+ }
+
+ /**
+ * Returns the text that will be used to filter this preference depending on
+ * user input.
+ * <p>
+ * If overridding and calling through to the superclass, make sure to prepend
+ * your additions with a space.
+ *
+ * @return Text as a {@link StringBuilder} that will be used to filter this
+ * preference. By default, this is the title and summary
+ * (concatenated with a space).
+ */
+ StringBuilder getFilterableStringBuilder() {
+ StringBuilder sb = new StringBuilder();
+ CharSequence title = getTitle();
+ if (!TextUtils.isEmpty(title)) {
+ sb.append(title).append(' ');
+ }
+ CharSequence summary = getSummary();
+ if (!TextUtils.isEmpty(summary)) {
+ sb.append(summary).append(' ');
+ }
+ // Drop the last space
+ sb.setLength(sb.length() - 1);
+ return sb;
+ }
+
+ /**
+ * Store this preference hierarchy's frozen state into the given container.
+ *
+ * @param container The Bundle in which to save the preference's icicles.
+ *
+ * @see #restoreHierarchyState
+ * @see #dispatchSaveInstanceState
+ * @see #onSaveInstanceState
+ */
+ public void saveHierarchyState(Bundle container) {
+ dispatchSaveInstanceState(container);
+ }
+
+ /**
+ * Called by {@link #saveHierarchyState} to store the icicles for this preference and its children.
+ * May be overridden to modify how freezing happens to a preference's children; for example, some
+ * preferences may want to not store icicles for their children.
+ *
+ * @param container The Bundle in which to save the preference's icicles.
+ *
+ * @see #dispatchRestoreInstanceState
+ * @see #saveHierarchyState
+ * @see #onSaveInstanceState
+ */
+ void dispatchSaveInstanceState(Bundle container) {
+ if (hasKey()) {
+ mBaseMethodCalled = false;
+ Parcelable state = onSaveInstanceState();
+ if (!mBaseMethodCalled) {
+ throw new IllegalStateException(
+ "Derived class did not call super.onSaveInstanceState()");
+ }
+ if (state != null) {
+ container.putParcelable(mKey, state);
+ }
+ }
+ }
+
+ /**
+ * Hook allowing a preference to generate a representation of its internal
+ * state that can later be used to create a new instance with that same
+ * state. This state should only contain information that is not persistent
+ * or can be reconstructed later.
+ *
+ * @return Returns a Parcelable object containing the preference's current
+ * dynamic state, or null if there is nothing interesting to save.
+ * The default implementation returns null.
+ * @see #onRestoreInstanceState
+ * @see #saveHierarchyState
+ * @see #dispatchSaveInstanceState
+ */
+ protected Parcelable onSaveInstanceState() {
+ mBaseMethodCalled = true;
+ return BaseSavedState.EMPTY_STATE;
+ }
+
+ /**
+ * Restore this preference hierarchy's frozen state from the given container.
+ *
+ * @param container The Bundle which holds previously frozen icicles.
+ *
+ * @see #saveHierarchyState
+ * @see #dispatchRestoreInstanceState
+ * @see #onRestoreInstanceState
+ */
+ public void restoreHierarchyState(Bundle container) {
+ dispatchRestoreInstanceState(container);
+ }
+
+ /**
+ * Called by {@link #restoreHierarchyState} to retrieve the icicles for this
+ * preference and its children. May be overridden to modify how restoreing
+ * happens to a preference's children; for example, some preferences may
+ * want to not store icicles for their children.
+ *
+ * @param container The Bundle which holds previously frozen icicles.
+ * @see #dispatchSaveInstanceState
+ * @see #restoreHierarchyState
+ * @see #onRestoreInstanceState
+ */
+ void dispatchRestoreInstanceState(Bundle container) {
+ if (hasKey()) {
+ Parcelable state = container.getParcelable(mKey);
+ if (state != null) {
+ mBaseMethodCalled = false;
+ onRestoreInstanceState(state);
+ if (!mBaseMethodCalled) {
+ throw new IllegalStateException(
+ "Derived class did not call super.onRestoreInstanceState()");
+ }
+ }
+ }
+ }
+
+ /**
+ * Hook allowing a preference to re-apply a representation of its internal
+ * state that had previously been generated by {@link #onSaveInstanceState}.
+ * This function will never be called with a null icicle.
+ *
+ * @param state The frozen state that had previously been returned by
+ * {@link #onSaveInstanceState}.
+ * @see #onSaveInstanceState
+ * @see #restoreHierarchyState
+ * @see #dispatchRestoreInstanceState
+ */
+ protected void onRestoreInstanceState(Parcelable state) {
+ mBaseMethodCalled = true;
+ if (state != BaseSavedState.EMPTY_STATE && state != null) {
+ throw new IllegalArgumentException("Wrong state class -- expecting Preference State");
+ }
+ }
+
+ public static class BaseSavedState extends AbsSavedState {
+ public BaseSavedState(Parcel source) {
+ super(source);
+ }
+
+ public BaseSavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public static final Parcelable.Creator<BaseSavedState> CREATOR =
+ new Parcelable.Creator<BaseSavedState>() {
+ public BaseSavedState createFromParcel(Parcel in) {
+ return new BaseSavedState(in);
+ }
+
+ public BaseSavedState[] newArray(int size) {
+ return new BaseSavedState[size];
+ }
+ };
+ }
+
+}