在 Preference.onSaveInstanceState 中保存什么

发布于 2024-11-17 21:09:42 字数 1728 浏览 4 评论 0原文

我正在为 Android 应用程序创建一些自定义首选项。

我创建的两个是 SeekBarPreferenceMultiSelectPreference

SeekBarPreference 非常简单,它继承自 DialogPreference 并具有自定义内容视图,其中显示 SeekBar

MultiSelectPreference 更高级一点,它打开一个 < code>Dialog 单击时有一个自定义 ListView 和一个按钮。当按下按钮时,会打开另一个Dialog,其中有一个通用的ListView

我应该在 onSaveInstanceState() 中保存什么 对于这些偏好?
对于 SeekBarPreference 我假设我需要保存值 if isPersistant() 是 false,也是当前滑块进度(这样我可以恢复),但浏览 Android 源代码后似乎并不像 EditTextPreference 关心存储当前文本,仅存储保存的值。

然而, DialogPreference 确实保存了对话框的当前状态,但似乎并没有保存其子项的状态,但这很难说,当我发现< a href="http://developer.android.com/reference/android/view/Window.html" rel="nofollow">Window 将在 onSaveInstanceState< 时执行/code> 被调用是因为它是抽象的并且我没有找到任何子类。

对这个问题的任何见解将不胜感激,我的目标是稍后开源代码,所以我想正确地做到这一点。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

俏︾媚 2024-11-24 21:09:42

经过大量测试和代码浏览后,这些是我的结论:

  • 如果视图连接到根视图,则不需要保存视图的状态,因为它们是在保存根视图时保存的,在我的情况下,这意味着我不需要保存视图的状态。不必保存 SeekBar 的状态,这是超类保存对话框时的句柄。
  • 如果您不持久,您应该始终保存您的值。
  • 您应该保存创建首选项后更改/可以更改的所有实例变量,这意味着可以使用设置器更改或可以随时间更改的变量。

尽管谷歌自己没有遵循最后一点,但他们自己是错误的,一个简单的例子说明了原因:
假设您有一个 PreferenceActivity,其中包含两件事;一个 ListPreference ,包含 10 个项目和一个泛型当按下时将一个项目添加到 ListPreference 的末尾。

现在假设用户启动应用程序并按下通用首选项,ListPreference 现在有 11 个项目。
用户现在打开 ListPreference。

如果应用程序关闭然后终止,实例将被保存,但 ListView 仅保存存储的值(如果它不是持久的),因此当它重新打开时,它仅包含最初的 10 个项目。

下面是一个显示问题的最小应用程序的示例,只需单击按钮,打开列表(应该有 4 个项目),关闭列表打开的应用程序,从 adb 杀死该应用程序并重新打开它,现在列表有三项。

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>    

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>    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文