不能放置两个SharedPreferences


90

遇到错误时,这种类型的sharedPreferences编辑器未定义放置double的方法。给了Eclipse一个快速修复,将强制类型转换添加到编辑器,但是当我这样做时仍然给出错误,为什么我不能放置double。

编码:

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();

    if (TextUtils.isEmpty(editBl.getText().toString())) {
        numberOfBl = 0;
    } else {
        numberOfBl = Integer.parseInt(editBl.getText().toString();

    }
    if (TextUtils.isEmpty(editSt.getText().toString())) {
        tonOfSt = 0;
    } else {
        tonOfSt = Double.parseDouble(editSt.getText().toString());

    }

    SharedPreferences prefs = getSharedPreferences(
            "SavedTotals", Context.MODE_PRIVATE);

    SharedPreferences.Editor editor = prefs.edit();

    editor.putInt("savedBl", numberOfBl);
    editor.putDouble("savedSt", tonOfSt);


    editor.commit();
}

2
您能指出遇到什么错误吗?
dumbfingers

1
请看问题的第一行
罗伯特·罗伯特

我想知道为什么Android家伙没有在API中实现putDouble?
luky

Answers:


336

不幸的是,那些建议使用putFloatgetFloat的人是错误的。将double转换为float可能会导致

  1. 精度损失
  2. 溢出
  3. 下溢
  4. 死猫

那些建议使用toStringparseString的方法没有错,但这是一种低效的解决方案。

解决此问题的正确方法是将double转换为其等效的“原始长位”并存储该long。读取值时,请转换回两倍。

因为这两种数据类型的大小相同,所以您不会损失精度,也不会引起{over,under}流。

Editor putDouble(final Editor edit, final String key, final double value) {
   return edit.putLong(key, Double.doubleToRawLongBits(value));
}

double getDouble(final SharedPreferences prefs, final String key, final double defaultValue) {
return Double.longBitsToDouble(prefs.getLong(key, Double.doubleToLongBits(defaultValue)));
}

或者,您可以将getter编写为:

double getDouble(final SharedPreferences prefs, final String key, final double defaultValue) {
if ( !prefs.contains(key))
        return defaultValue;

return Double.longBitsToDouble(prefs.getLong(key, 0));
}

9
如此美丽,干净,优雅。
Bogdan Alexandru

9
尽管与Android生态系统中的其他API(如parceable和bundles)一样,putDouble方法仍将是不错且一致的。Google再次变得又快又草率的典型情况。

2
为什么将其另存为字符串效率低下?
KKO 2014年

2
@KKO long数据类型是64位二进制补码整数。因此仅占用4个字节。但是,如果您将该double值存储为字符串,则会破坏存储并使其残骸!!
semsamot

1
prefs.getLong(key,0d)不正确,不是双精度型。应该没有d。
Ahmed Hegazy 2014年

27

Kotlin扩展方式(比使用奇怪的utils类或其他方法漂亮得多)

fun SharedPreferences.Editor.putDouble(key: String, double: Double) =
    putLong(key, java.lang.Double.doubleToRawLongBits(double))

fun SharedPreferences.getDouble(key: String, default: Double) =
    java.lang.Double.longBitsToDouble(getLong(key, java.lang.Double.doubleToRawLongBits(default)))

2
太好了,我正是在考虑将其放置在此处。谢谢!
wzieba

16

我所做的是将首选项保存为字符串:

getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit().putString("double", "0.01").commit();

然后使用Double.parseDouble来检索双精度型:

Double.parseDouble(getSharedPreferences("PREFERENCE", MODE_PRIVATE).getString("double", "0.01"));

4
您正在浪费存储空间。它也比doubleToRawLongBits已经提到的方法要慢得多。这是错误的方法,不是因为它不起作用,而是因为它效率很低。
copolii 2014年

10
@copolii当然可以。实际上,在行业中,在99%的情况下,实际上并没有什么大不了的,实际上,在结交新朋友时,这可能更易于阅读和理解。
丹尼斯·L

@DennisL #PracticalDev
Aba

9

您可以始终实现SharedPreferences并包装android实现。

package com.company.sharedpreferences;

import android.content.Context;
import android.content.SharedPreferences;


import java.util.Map;
import java.util.Set;

public class EnhancedSharedPreferences implements SharedPreferences {

    public static class NameSpaces {
        public static String MY_FUN_NAMESPACE = "MyFunNameSpacePrefs";
    }

    public static EnhancedSharedPreferences getPreferences(String prefsName) {
        return new EnhancedSharedPreferences(SomeSingleton.getInstance().getApplicationContext().getSharedPreferences(prefsName, Context.MODE_PRIVATE));
    }

    private SharedPreferences _sharedPreferences;

    public EnhancedSharedPreferences(SharedPreferences sharedPreferences) {
        _sharedPreferences = sharedPreferences;
    }

    //region Overrides

    @Override
    public Map<String, ?> getAll() {
        return _sharedPreferences.getAll();
    }

    @Override
    public String getString(String key, String defValue) {
        return _sharedPreferences.getString(key, defValue);
    }

    @Override
    public Set<String> getStringSet(String key, Set<String> defValues) {
        return _sharedPreferences.getStringSet(key, defValues);
    }

    @Override
    public int getInt(String key, int defValue) {
        return _sharedPreferences.getInt(key, defValue);
    }

    @Override
    public long getLong(String key, long defValue) {
        return _sharedPreferences.getLong(key, defValue);
    }

    @Override
    public float getFloat(String key, float defValue) {
        return _sharedPreferences.getFloat(key, defValue);
    }

    @Override
    public boolean getBoolean(String key, boolean defValue) {
        return _sharedPreferences.getBoolean(key, defValue);
    }

    @Override
    public boolean contains(String key) {
        return _sharedPreferences.contains(key);
    }

    @Override
    public Editor edit() {
        return new Editor(_sharedPreferences.edit());
    }

    @Override
    public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
        _sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
    }

    @Override
    public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
        _sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
    }

    //endregion

    //region Extension

    public Double getDouble(String key, Double defValue) {
        return Double.longBitsToDouble(_sharedPreferences.getLong(key, Double.doubleToRawLongBits(defValue)));
    }

    //endregion

    public static class Editor implements SharedPreferences.Editor {

        private SharedPreferences.Editor _editor;

        public Editor(SharedPreferences.Editor editor) {
            _editor = editor;
        }

        private Editor ReturnEditor(SharedPreferences.Editor editor) {
            if(editor instanceof Editor)
                return (Editor)editor;
            return new Editor(editor);
        }

        //region Overrides

        @Override
        public Editor putString(String key, String value) {
            return ReturnEditor(_editor.putString(key, value));
        }

        @Override
        public Editor putStringSet(String key, Set<String> values) {
            return ReturnEditor(_editor.putStringSet(key, values));
        }

        @Override
        public Editor putInt(String key, int value) {
            return ReturnEditor(_editor.putInt(key, value));
        }

        @Override
        public Editor putLong(String key, long value) {
            return ReturnEditor(_editor.putLong(key, value));
        }

        @Override
        public Editor putFloat(String key, float value) {
            return ReturnEditor(_editor.putFloat(key, value));
        }

        @Override
        public Editor putBoolean(String key, boolean value) {
            return ReturnEditor(_editor.putBoolean(key, value));
        }

        @Override
        public Editor remove(String key) {
            return ReturnEditor(_editor.remove(key));
        }

        @Override
        public Editor clear() {
            return ReturnEditor(_editor.clear());
        }

        @Override
        public boolean commit() {
            return _editor.commit();
        }

        @Override
        public void apply() {
            _editor.apply();
        }

        //endregion

        //region Extensions

        public Editor putDouble(String key, double value) {
            return new Editor(_editor.putLong(key, Double.doubleToRawLongBits(value)));
        }

        //endregion
    }
}

这是正确的答案。我希望我在开始打字之前就已经看到了。仅在编辑器方法中返回“ this”会更有效吗?它使您不必调用“ instanceof”方法。还是您尝试过而导致问题?
copolii

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.