【问题标题】:Calling setDefaultValue() on a custom Preference class does not set the default value. Why?在自定义 Preference 类上调用 setDefaultValue() 不会设置默认值。为什么?
【发布时间】:2011-02-03 13:01:58
【问题描述】:

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

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

所以我想,当我把一些硬编码的值放在那里时会发生什么(你知道,也许我做错了什么,这不是第一次)。好吧,我仍然收到null 的回复。

任何想法我做错了什么?

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

我做了一个解决方法:

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

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

【问题讨论】:

  • 在调用 getValue() 之前是否调用了 setDefaultValue()?我在一个preferences.xml 文件中设置了我的默认首选项,该文件在创建我的首选项视图之前被读取 - 你如何设置你的默认值?
  • 是的,但在代码中。问题是在应用程序首次启动之前我不知道默认值。所以我尝试在用户第一次打开preferenceactivity时设置它

标签: android android-preferences preferenceactivity preference listpreference


【解决方案1】:

我终于找到了the solution(在 StackOverflow 之外的某个地方,一次)。

当您创建自定义 Preference 类时,

  1. 你需要像XåpplI'-I0llwlg'I -指出的那样实现onSetInitialValue
  2. 需要实现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() 终于 也会为自定义首选项加载android:defaultValue。仍然无法修复 null 和 false,但对于在其他地方发布的内容,有一些解决方法。

【讨论】:

    【解决方案2】:

    如果您想在调用 setDefaultValue() 后调用 getValue() 以在您的 PreferenceActivity 首次打开时检索默认值,则需要在您的 Preference 子类中覆盖 onSetInitialValue()。否则,调用getValue() 时不会设置默认值,它会返回null(如您所见)。

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

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

    DEFAULT_VALUE 只是 Preference 中的一个私有常量,用于在无法检索持久 int 的情况下使用。 setValue() 是补充 getValue() 公共 getter 的公共 setter,应该看起来像这样:

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

    有关onSetInitialValue() 的更多信息,请参阅API 文档here

    查看 Preference 类 (here) 的源代码以了解为什么需要实现 onSetInitialValue() 也是一个好主意。特别是看setDefaultValue(),再看dispatchSetInitialValue()

    【讨论】:

      【解决方案3】:

      setDefaultValue 不像你想象的那样工作。看看the sourcePreference.java,你就会明白这一切背后的逻辑。

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

      【讨论】:

      • 好吧,我真的不能,因为条目不是静态的。我看到的唯一(肮脏)解决方法是在我设置默认值时设置的首选项中设置一个标志,然后使用 setValue()。
      【解决方案4】:

      我将首选项.xml 转换为代码。所有setDefaultValues 都在那里运行良好。

      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:我发现这种方式比自定义所有偏好或其他答案更小更清晰。

      【讨论】:

        【解决方案5】:

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

        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>
        

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            【解决方案7】:

            我认为这也适用于任何时候。

             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。

            【讨论】:

            • 这不起作用。首选项值已设置,但至少对于 ListPreference,不会填充列表。
            猜你喜欢
            • 1970-01-01
            • 2011-08-01
            • 1970-01-01
            • 2021-08-22
            • 1970-01-01
            • 1970-01-01
            • 2010-10-28
            • 1970-01-01
            相关资源
            最近更新 更多