【问题标题】:PreferenceActivity: save value as integerPreferenceActivity:将值保存为整数
【发布时间】:2011-04-12 21:22:14
【问题描述】:

在我的偏好活动中使用简单的EditTextPreference

<EditTextPreference
    android:key="SomeKey"
    android:title="@string/some_title"
    android:summary="..."
    android:numeric="integer"
    android:maxLength="2"
/>

有没有办法将此配置值保存为整数?现在似乎它只允许输入数字,但该值仍保存为字符串:

调用:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = preferences.getInt("SomeKey", -1);

扔给我java.lang.ClassCastException: java.lang.String,然后:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String value = preferences.getString("SomeKey", "-1");

成功检索值。

如何让PreferenceActivity默认将值保存为整数?

【问题讨论】:

    标签: android sharedpreferences preferenceactivity


    【解决方案1】:

    您可以扩展 EditTextPreference:

    public class IntEditTextPreference extends EditTextPreference {
    
        public IntEditTextPreference(Context context) {
            super(context);
        }
    
        public IntEditTextPreference(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public IntEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        protected String getPersistedString(String defaultReturnValue) {
            return String.valueOf(getPersistedInt(-1));
        }
    
        @Override
        protected boolean persistString(String value) {
            return persistInt(Integer.valueOf(value));
        }
    }
    

    最好覆盖 onSetInitialValue() 和 setText() 方法,但是你必须从基类中复制一些代码。上面的解决方案更简单,但它非常棘手 - “字符串”方法对整数做一些事情。尽量不要进一步扩展这个类;-)

    您可以通过以下方式从 XML 中使用它:

    <package.name.IntEditTextPreference
        android:key="SomeKey"
        android:title="@string/some_title"
        android:summary="..."
        android:numeric="integer"
        android:maxLength="2"
    />
    

    【讨论】:

    • @Brutall,我想通过改进代码来感谢你。但是有人跟我说新代码……太长了,他拒绝了。哦,但是如果旧代码不好,需要更换,但人们不这样做,因为新代码……长,人们会怎么做?即使它更好。哦,天哪,太棒了!这是程序员的地方?我有一些开源项目,我愿意对我的代码进行任何更改。让他多么丢脸!无论如何,非常感谢你,布鲁托。
    • 顺便说一句,我所做的就是:将输入类型设置为数字;添加TextWatcher,确保用户输入的文本不为空,默认值为0
    • 我在return String.valueOf(getPersistedInt(-1)); 上遇到运行时错误,由于该行而无法启动活动
    • @user942821 但是没有默认类型 int 的首选项吗?这太疯狂了,它不仅存在,还需要所有这些额外的代码。为什么默认没有“EditIntPreference”标签?
    • @user942821 这很烦人,因为我只想公开一些内部整数首选项以进行调试,它们通常甚至不是用户应该编辑的!
    【解决方案2】:

    即使您设置了 android:numeric="integer" ,它也会是文本首选项 - 正如其名称所暗示的那样。您可以使用 Integer.valueOf() 轻松地将字符串值转换为 int。 您也可以覆盖 PreferenceActivity 以在退出时自动进行转换。


    我认为最好的解决方案是编写简单的方法来从偏好中获取此值。比如:

    public static int getSomePref(Context context) {
        SharedPreferences prefs =
            PreferenceManager.getDefaultSharedPreferences(context);
        String value = prefs.getString("SomeKey", null);
        return value == null ? -1 : Integer.valueOf(value);
    }
    

    然后你可以很容易地从你的代码中使用它。

    【讨论】:

    • 我在哪里可以覆盖它?默认情况下PreferenceActivity会自动保存,我应该重写一些获取值的方法还是全部保存自己?
    • 好的,更改偏好类型不好,因为您可能会遇到 ClassCastException 问题。我已经更新了我的答案。
    • 是的,我自己也考虑过 wrapper,但我还是不喜欢这个解决方案……SharedPreferences 已经有getInt 方法,所以仍然希望以某种方式找到一种方法来告诉PreferenceActivity 将值保存为 int - 所有功能都在那里......只是不能按预期工作......
    • 你总是可以编写自己的 Preference 类。
    • OP 已询问如何将值保存为整数。这个答案没有解决这个问题,它只是提供了一种解决方法,可以在保存 STRING 的同时取回 Integer。
    【解决方案3】:

    即使答案已被接受,我还是想分享一种更短的方法来实现这一点:

    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    int value = Integer.parseInt(preferences.getString("SomeKey", "-1"));
    

    由于您已经设置了只能输入数字,因此不会出现任何异常。 尚未完成我的答案:

    <EditTextPref
        android:key="SomeKey"
        android:title="@string/some_title"
        android:summary="..."
        android:numeric="integer"
        android:maxLength="2" />
    

    【讨论】:

    • 如果你希望值被持久化为“int”,即你想使用preferences.getInt()来加载首选项,你需要使用接受的答案。
    • 2019 更新:android:numeric 现已弃用,您应该改用 android:inputType="number"
    【解决方案4】:

    我遇到了同样的问题。 (我希望 SharedPreference 给我一个端口号,我将其作为 defaultValue 存储在首选项 xml 文件中)。

    实现所有 SharedPreferences 方法会很费力,因此我认为最好在类中编写一个实例化 SharedPreferences 的自定义方法,正如broot 建议的那样。

    您也可以在需要的行中使用 Integer 的 Static 方法:

    int number = Integer.valueOf(settings.getString("myNumberString", "0"));
    

    【讨论】:

      【解决方案5】:

      我认为这是我能想到的最短的一个:

      int CheckInterval = Integer.parseInt(sharedPreferences.getString("check_frequency","60"));
      

      【讨论】:

        【解决方案6】:

        我知道这是一个已被接受的答案的老问题,但我认为我的解决方案可能对寻找更完整答案的人有所帮助。我刚刚改进了@broot 的回答,我的解决方案就出来了:

        重写 EditTextPreference 以提供文本到 int 的转换:

        public class IntEditTextPreference extends EditTextPreference implements EditTextPreference.OnBindEditTextListener {
            private String mText;
            
            public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
                super(context, attrs, defStyleAttr, defStyleRes);
                setOnBindEditTextListener(this);
            }
        
            public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
                setOnBindEditTextListener(this);
            }
        
            public IntEditTextPreference(Context context, AttributeSet attrs) {
                super(context, attrs);
                setOnBindEditTextListener(this);
            }
        
            public IntEditTextPreference(Context context) {
                super(context);
                setOnBindEditTextListener(this);
            }
        
            /**
             * Saves the text to the current data storage.
             *
             * @param text The text to save
             */
            public void setText(String text) {
                final boolean wasBlocking = shouldDisableDependents();
        
                mText = text;
        
                int value = Integer.parseInt(text);
        
                persistInt(value);
        
                final boolean isBlocking = shouldDisableDependents();
                if (isBlocking != wasBlocking) {
                    notifyDependencyChange(isBlocking);
                }
        
                notifyChanged();
            }
        
            /**
             * Gets the text from the current data storage.
             *
             * @return The current preference value
             */
            public String getText() {
                return mText;
            }
        
            @Override
            protected void onSetInitialValue(Object defaultValue) {
                int value;
                if (defaultValue != null) {
                    String strDefaultValue = (String) defaultValue;
        
                    int defaultIntValue = Integer.parseInt(strDefaultValue);
                    value = getPersistedInt(defaultIntValue);
                } else {
                    value = getPersistedInt(0);
                }
        
                setText(Integer.toString(value));
            }
        
            @Override
            public boolean shouldDisableDependents() {
                return TextUtils.isEmpty(mText) || super.shouldDisableDependents();
            }
        
            @Override
            public void onBindEditText(@NonNull EditText editText) {
                editText.setInputType(InputType.TYPE_CLASS_NUMBER);
            }
        }
        

        在首选项 xml 中:

        <your.package.here.IntEditTextPreference
                    android:key="some_key"
                    android:title="@string/some_title"
                    android:defaultValue="5"
                    app:useSimpleSummaryProvider="true"/>
        

        注意:不要使用 android:numeric 或 android:inputType。由于 EditTextPreference 不是 EditText 本身,因此设置这些属性将无济于事。为了从 EditTextPreference 打开的 Dialog 中获得所需的 EditText 效果,只需通过实现 EditTextPreference.OnBindEditTextListener 在自定义 EditTextPreference 中设置输入类型,如上面的代码所示。

        这对我有用。

        【讨论】:

          猜你喜欢
          • 2010-12-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-12
          • 2014-06-21
          • 1970-01-01
          相关资源
          最近更新 更多