简体   繁体   English

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

[英]Calling setDefaultValue() on a custom Preference class does not set the default value. Why?

I'm extending PreferenceActivity for my settings screen.我正在为我的设置屏幕扩展PreferenceActivity 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.在此自定义首选项(从ListPreference扩展)中,我希望能够设置默认值,因此我覆盖了setDefaultValue()方法。 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 .当我尝试使用getValue()函数读取此值时,它只返回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.好吧,我仍然返回null

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.在 xml 文件中设置 defaultValue 并不是一个真正的选项,因为在我检索它们之前这些值是未知的。

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这样我在收集数据时设置了默认首选项

I finally found the solution (somewhere besides StackOverflow, for once).我终于找到了解决方案(一次除了 StackOverflow 之外)。

When you create a custom Preference class,当您创建自定义 Preference 类时,

  1. You need to implement onSetInitialValue as XåpplI'-I0llwlg'I - pointed out您需要将onSetInitialValue实现为XåpplI'-I0llwlg'I -指出
  2. You also need to implement onGetDefaultValue(TypedArray a, int index)需要实现onGetDefaultValue(TypedArray a, int index)

For example, if the custom preference is saved as an int,例如,如果自定义首选项保存为 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.现在PreferenceManager.setDefaultValues()最终也为自定义首选项加载了android:defaultValue Still no fix for nulls and false, but there are workarounds for those posted elsewhere.仍然没有修复空值和假值,但有针对其他地方发布的解决方法。

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.如果您想在调用setDefaultValue() getValue()后调用getValue()以在第一次打开 PreferenceActivity 时检索默认值,则需要覆盖 Preference 子类中的onSetInitialValue() Otherwise, the default value will not be set when you call getValue() and it will return a null (as you experienced).否则,当您调用getValue()时不会设置默认值,它将返回一个null (如您所见)。

For example, if your default value is an integer, your onSetInitialValue() might look like this:例如,如果您的默认值是一个整数,您的onSetInitialValue()可能如下所示:

@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. DEFAULT_VALUE只是 Preference 中的一个私有常量,在无法检索持久化 int 时使用。 setValue() is the public setter to complement your getValue() public getter, and should look something like this: setValue()是补充getValue()公共 getter 的公共 setter,应该如下所示:

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 .有关onSetInitialValue()更多信息,请参阅此处的 API 文档。

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.查看 Preference 类的源代码( 这里)来理解为什么需要实现onSetInitialValue()也是一个好主意。 In particular, have a look at setDefaultValue() , and then look at dispatchSetInitialValue() .特别是,看看setDefaultValue() ,然后看看dispatchSetInitialValue()

setDefaultValue doesn't work the way you think it does. setDefaultValue并不像您认为的那样工作。 Look at the source of Preference.java and you'll the logic behind it all.查看Preference.java 的源代码,您将了解其背后的逻辑。

The preferred way to set a default is to specify the android:defaultValue attribute in the preferences.xml file of your app.设置默认值的首选方法是在应用程序的preferences.xml android:defaultValue文件中指定android:defaultValue属性。

I converted preferences .xml to code.我将首选项.xml转换为代码。 All setDefaultValue s works well there.所有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

more info 更多信息

PS: I found this way more smaller and clear than customizing all preferences or other answers. PS:我发现这种方式比自定义所有偏好或其他答案更小更清晰。

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 使用它:

<?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>

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
    }

}

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.此代码将检测对话框即将启动的时间,并使用您的默认值填充对话框中的 EditText 或 List。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM