在自定义 Preference 类上调用 setDefaultValue() 不会设置默认值。为什么?

发布于 2024-10-15 17:15:57 字数 575 浏览 9 评论 0 原文

我正在为我的设置屏幕扩展 PreferenceActivity。在这个偏好活动中,我有几个偏好,其中之一是定制的。问题如下:

在这个自定义首选项(从 ListPreference 扩展)中,我希望能够设置默认值,因此我重写了 setDefaultValue() 方法。在这种方法中,我做了一些解析,因此它将采用正确的值。当我尝试使用 getValue() 函数读取此值时,它仅返回 null

所以我想,当我只是在其中放入一些硬编码值时会发生什么(你知道,也许我做错了什么,这不是第一次)。好吧,我仍然得到 null 回来。

有什么想法我做错了吗?

编辑:
在 xml 文件中设置 defaultValue 实际上并不是一个选项,因为在我检索这些值之前,这些值是未知的。

我做了一个解决方法:

  • 当应用程序第一次启动时:获取数据
  • 在首选项中设置值。

这样我在收集数据时设置默认首选项

I'm extending PreferenceActivity for my settings screen. In this preference activity i have a couple of preferences one of which is custom made. The problem is as follows:

in this custom preference (which extends from ListPreference) i want to be able to set the default value, so i override the setDefaultValue() method. In this method i do some parsing so it'll take the correct value. When i'm trying to read this value with the getValue() function it just returns null.

So i figured, what happens when i just put some hardcoded value in there (you know, maybe i did something wrong, wouldn't be the first time). Well, i still get null back.

Any ideas what i'm doing wrong?

Edit:
Setting the defaultValue in the xml file isn't really an option because the values aren't known until i retrieve them.

I made a workaround:

  • When app is started for the first time: get data
  • Set the values in the preference.

This way i set the default preference when i'm collection the data

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

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

发布评论

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

评论(7

少女净妖师 2024-10-22 17:15:57

我终于找到了解决方案(除了StackOverflow之外,这一次) 。

创建自定义 Preference 类时,

  1. 您需要将 onSetInitialValue 实现为 XåpplI'-I0llwlg'I - 指出
  2. 需要实现< code>onGetDefaultValue(TypedArray a, int index)

例如,如果自定义首选项保存为 int,

@Override
protected void onSetInitialValue(boolean restore, Object defaultValue) {
    setValue(restore ? getPersistedInt(FALLBACK_DEFAULT_VALUE) : (Integer) defaultValue);
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
   return a.getInteger(index, FALLBACK_DEFAULT_VALUE);
}

现在 PreferenceManager.setDefaultValues() finally 也会加载自定义首选项的 android:defaultValue 。仍然没有解决 null 和 false 的问题,但是对于其他地方发布的问题有一些解决方法。

I finally found the solution (somewhere besides StackOverflow, for once).

When you create a custom Preference class,

  1. You need to implement onSetInitialValue as XåpplI'-I0llwlg'I - pointed out
  2. You also need to implement onGetDefaultValue(TypedArray a, int index)

For example, if the custom preference is saved as an int,

@Override
protected void onSetInitialValue(boolean restore, Object defaultValue) {
    setValue(restore ? getPersistedInt(FALLBACK_DEFAULT_VALUE) : (Integer) defaultValue);
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
   return a.getInteger(index, FALLBACK_DEFAULT_VALUE);
}

Now PreferenceManager.setDefaultValues() finally loads the android:defaultValue for the custom preferences too. Still no fix for nulls and false, but there are workarounds for those posted elsewhere.

笑红尘 2024-10-22 17:15:57

如果您想在调用 setDefaultValue() 后调用 getValue() 以在 PreferenceActivity 首次打开时检索默认值,则需要重写 onSetInitialValue()< /code> 在您的 Preference 子类中。否则,当您调用 getValue() 时,将不会设置默认值,并且它将返回 null (如您所经历的)。

例如,如果您的默认值是整数,则 onSetInitialValue() 可能如下所示:

@Override
protected void onSetInitialValue(boolean restore, Object defaultValue)
{
    setValue(restore ? getPersistedInt(DEFAULT_VALUE) : (Integer) defaultValue);
}

DEFAULT_VALUE 只是 Preference 内的一个私有常量,用于在持久化时使用int 无法检索。 setValue() 是公共 setter,用于补充 getValue() 公共 getter,并且应如下所示:

public int getValue()
{
    return mValue;
}

public void setValue(int value)
{
    if (value != mValue)
    {
        mValue = value;
        persistInt(value);
    }
}

有关 onSetInitialValue() 的更多信息>,参考API文档 这里

查看 Preference 类的源代码也是一个好主意(这里)来理解为什么需要实现onSetInitialValue()。特别是,请查看 setDefaultValue(),然后查看 dispatchSetInitialValue()

If you want to call getValue() after calling setDefaultValue() to retrieve a default value the first time your PreferenceActivity opens, you need to override onSetInitialValue() in your Preference subclass. Otherwise, the default value will not be set when you call getValue() and it will return a null (as you experienced).

For example, if your default value is an integer, your onSetInitialValue() might look like this:

@Override
protected void onSetInitialValue(boolean restore, Object defaultValue)
{
    setValue(restore ? getPersistedInt(DEFAULT_VALUE) : (Integer) defaultValue);
}

DEFAULT_VALUE is just a private constant inside the Preference to be used in case the persisted int cannot be retrieved. setValue() is the public setter to complement your getValue() public getter, and should look something like this:

public int getValue()
{
    return mValue;
}

public void setValue(int value)
{
    if (value != mValue)
    {
        mValue = value;
        persistInt(value);
    }
}

For more information about onSetInitialValue(), refer to the API documentation here.

It's also a good idea to look at the source code of the Preference class (here) to understand why onSetInitialValue() needs to be implemented. In particular, have a look at setDefaultValue(), and then look at dispatchSetInitialValue().

老旧海报 2024-10-22 17:15:57

setDefaultValue 并不像您想象的那样工作。看看 Preference.java 的源代码,您将了解其背后的逻辑。

设置默认值的首选方法是在应用的 preferences.xml 文件中指定 android:defaultValue 属性。

setDefaultValue doesn't work the way you think it does. Look at the source of Preference.java and you'll the logic behind it all.

The preferred way to set a default is to specify the android:defaultValue attribute in the preferences.xml file of your app.

感悟人生的甜 2024-10-22 17:15:57

我将首选项 .xml 转换为代码。所有 setDefaultValue 都可以正常工作。

val screen = preferenceManager.createPreferenceScreen(context)

val editText = EditTextPreference(context).apply {
         setIcon(R.drawable.lobat_cloud)
         key = "key"
         title = "MyPreferences"
         ...

         setDefaultValue("My Default Value")
      }

screen.addPreference(editText)

// add other preferences

preferenceScreen = screen

更多信息

PS:我发现这种方式更小更清晰而不是自定义所有首选项或其他答案。

I converted preferences .xml to code. All setDefaultValues works well there.

val screen = preferenceManager.createPreferenceScreen(context)

val editText = EditTextPreference(context).apply {
         setIcon(R.drawable.lobat_cloud)
         key = "key"
         title = "MyPreferences"
         ...

         setDefaultValue("My Default Value")
      }

screen.addPreference(editText)

// add other preferences

preferenceScreen = screen

more info

P.S: I found this way more smaller and clear than customizing all preferences or other answers.

菩提树下叶撕阳。 2024-10-22 17:15:57

您可以扩展首选项并在构建过程中设置默认值,如下所示:

package com.example.package.preference;

public class CustomPreference extends ListPreference{

public CustomPreference(Context context) {
    super(context);
    init();
}

public CustomPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

private void init() {
    Object anyDefaultValueFromCode = ...
    setDefaultValue(anyDefaultValueFromCode );
}
}

然后您可以像这样从 XML 使用它:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="alarm_prefs_screen"
android:title="@string/set_alarm" >

<com.example.package.preference.CustomPreference
    android:key="custom_preference"
    android:title="@string/any_title" />

</PreferenceScreen>

You can extend preference and set the default value during constructing like this:

package com.example.package.preference;

public class CustomPreference extends ListPreference{

public CustomPreference(Context context) {
    super(context);
    init();
}

public CustomPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

private void init() {
    Object anyDefaultValueFromCode = ...
    setDefaultValue(anyDefaultValueFromCode );
}
}

then you can use it from XML like this:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="alarm_prefs_screen"
android:title="@string/set_alarm" >

<com.example.package.preference.CustomPreference
    android:key="custom_preference"
    android:title="@string/any_title" />

</PreferenceScreen>
灯角 2024-10-22 17:15:57

这就是我所做的并为我工作:

class DefaultValueEditTextPreference : androidx.preference.EditTextPreference {
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    @Suppress("unused")
    constructor(context: Context?) : super(context)

    init {
        text = ... //the default, dynamic text that you want to have
    }

}

This is what I did and worked for me:

class DefaultValueEditTextPreference : androidx.preference.EditTextPreference {
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    @Suppress("unused")
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    @Suppress("unused")
    constructor(context: Context?) : super(context)

    init {
        text = ... //the default, dynamic text that you want to have
    }

}
掐死时间 2024-10-22 17:15:57

我认为这在任何时候都有效。

 Preference aaa = (Preference) findPreference("xxx");
 aaa.setOnPreferenceClickListener(new OnPreferenceClickListener() {

              public boolean onPreferenceClick(Preference preference) {

                    // For edit text preference
                    ((EditTextPreference)preference).getEditText().setText("foobar");


                    // for list preference
                    (ListPreference)preference).setValue("foobar");

                    // etc ...

            return true;
              }
 });

此代码将检测对话框何时即将启动,并使用默认值填充对话框中的 EditText 或 List。

I think this works too at anytime.

 Preference aaa = (Preference) findPreference("xxx");
 aaa.setOnPreferenceClickListener(new OnPreferenceClickListener() {

              public boolean onPreferenceClick(Preference preference) {

                    // For edit text preference
                    ((EditTextPreference)preference).getEditText().setText("foobar");


                    // for list preference
                    (ListPreference)preference).setValue("foobar");

                    // etc ...

            return true;
              }
 });

This code will detect when the dialog is about to launch and populate the EditText or List in the dialog with your default value.

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