DialogPreference是否在我希望的时候不保存首选项?

时间:2018-09-27 15:32:23

标签: android sharedpreferences dialog-preference

我写了一个简单的标准DialogPreference,它工作正常,除了在我期望的情况下不会将首选项保存为默认共享首选项。

1)打开应用程序,并且主活动显示默认共享首选项= 1时foo的值

2)进入设置

3)单击foo设置,这将打开我的DialogPreference并显示value = 1

4)输入值3

5)使用“确定”按钮关闭DialogPreference

*****默认共享首选项foo现在应该为3

6)单击foo设置,这将打开我的DialogPreference并显示value = 1

*****,这样我的DialogPreference不会将首选项保存为默认的共享首选项吗?

7)取消对话框

8)返回主要活动,该活动显示默认共享首选项= 3时foo的值

*****,所以我的DialogPreference确实将首选项保存为默认的共享首选项

9)进入设置

10)单击foo设置,这将打开我的DialogPreference并显示值为3

为什么在第(6)步中默认的共享首选项foo = 3的值为何?

似乎只有在流程从设置列表返回到主活动时,该首选项才被保存为默认的共享首选项,这与将首选项保存在DialogPreference的onDialogClosed方法中是很直观的。

MyDialogPreference

public class MyDialogPreference extends DialogPreference
{
private static final String DEFAULT_VALUE = "0";
private String value = DEFAULT_VALUE;
private EditText editText;

public MyDialogPreference(Context context, AttributeSet attrs)
{
    super(context, attrs);
    setDialogLayoutResource(R.layout.constrained_integer_preference);
}

@Override
public void onBindDialogView(View view)
{
    super.onBindDialogView(view);

    editText = (EditText) view.findViewById(R.id.edit);
    editText.setText("" + value);
}

@Override
protected void onDialogClosed(boolean positiveResult)
{

    if (positiveResult)
    {
        persistString(editText.getText().toString());
    }

    super.onDialogClosed(positiveResult);
}

@Override
protected Object onGetDefaultValue(TypedArray typedArray, int index)
{
    return typedArray.getString(index);
}

@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
{

    if (restorePersistedValue)
    {
        value = getPersistedString(DEFAULT_VALUE);
    }
    else
    {
        value = (String) defaultValue;

        if (shouldPersist())
        {
            persistString(value);
        }

    }

}

}

编辑:所以看来我使用DialogPreference处理的首选项没有键,这导致了所有问题。但是我已经在这个DialogPreference的preferences.xml文件中指定了键。我已经尽力使密钥被识别,但是没有任何作用。

谁能告诉我如何从references.xml文件中获取DialogPreference来接收android:key?

preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<org.mycompany.myproject.MyDialogPreference
    android:defaultValue="11"
    android:dialogLayout="@layout/my_preference"
    android:inputType="number"
    android:key="MY_KEY"
    android:selectAllOnFocus="true"
    android:singleLine="true"
    android:summary="summary"
    android:title="My Preference" />
</PreferenceScreen>

2 个答案:

答案 0 :(得分:0)

您必须实现OnPreferenceChangeListener和/或调用notifyChanged()

除非您提供该DialogPreference的代码,否则很难重现该问题。

答案 1 :(得分:0)

<罢工> 在某些时候,我总是觉得自己正在入侵Android,这绝对是黑客。

最初,我认为我要解决的问题是框架忽略了我的android:key,因为getKey()返回一个空字符串,但这不能成立,因为它在启动PreferenceScreen时会获得持久值,并且关闭DialogPreference时,将更改后的值保存到共享的首选项中。

所以看来我正在解决的问题是,该框架将持久性值读入内部成员,然后使用内部成员,直到流程退出了优先级框架,而在DialogPreference关闭后没有刷新它们。

但是我终于找到了一种使PreferenceScreen刷新其内部成员中保存的首选项持久性值的方法。尽管这并不是真正的刷新,但它是一个hack。

所以我要做的基本上是丢弃PreferenceScreen并创建一个新的。为此,我在addPreferencesFromResource(R.xml.preferences)之前直接将以下代码添加到SettingsFragment.onCreate方法中。

    SharedPreferences.OnSharedPreferenceChangeListener prefListener = (prefs, key) ->
    {
        setPreferenceScreen(null);
        addPreferencesFromResource(R.xml.preferences);
    };

    PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()).registerOnSharedPreferenceChangeListener(prefListener);

这可能是不好的。我已经反复测试了它,尽管还不是很全面,并且到目前为止还没有看到任何不利影响。

因此,利用此技巧,我现在可以从PreferenceScreen重复打开DialogPreference,保存新值,然后使用先前更新的值返回DialogPreference。

我不相信我的hack是达到此结果的预期方式,但是经过数天的搜索源代码和google的答案,我什么都没找到。

我将这个答案留给其他面临相同问题并且足够勇敢尝试我的黑客的人。如果(可能在什么时候)发现hack的任何问题,我将更新答案。

更好的是,如果其他任何人都可以提供首选的解决方案,请指出我做错了导致问题的原因,请这样做。

编辑:在工作了这么长时间之后,这种黑客终于并始终如一地崩溃了。

但是在删除hack时,我以崭新的方式解决了该问题,并利用确定对话框已获得偏好键的事实,对此问题使用了此修复程序,效果很好。

我将这行代码添加到onBindDialogView的开头

value = getSharedPreferences().getString(getKey(), "-1");

哪个使得对onGetDefaultValue和onSetInitialValue的调用是多余的,但是它们只是不能按预期工作,至少对我来说不是。

编辑: 天哪,我讨厌这个!

我没有注意到在较早的重构过程中,删除了更新onDialogClosed中DialogPreference内部值的代码行。

通常这很简单,在检查所有其他内容时,我错过了这个小的更改。

我只是在回购上的代码审查期间才注意到它,现在我感到很傻。因此最后不需要其他代码。