SharedPreferences是Android官方为我们提供的一个非常简单易用的本地持久化数据存储工具,我们可以很轻松的利用它存储一些常用的键值对。在App退出关闭后,其存储的数据依然有效,很多不需要存储复杂数据和大数据的应用,只靠SharedPreferences就能满足数据本地存储的需求了。

SharedPreferences可以支持的有5种数据类型,分别是:int、long、boolean、float、String,无论是用put还是get方法,其基本的数据类型只有这5种。细心的朋友会发现,咦,怎么没有double呢?

关于SharedPreferences为何不支持double类型,我在Google上没找到答案。当然了,作为一个开发者,不知道这个理由也无所谓,但我们确实在很多时候需要在SharedPreferences里面保存double类型的数据,那该怎么办呢?

方法一:直接保存成float型

大概这是头脑转的最快的那些人首先想到的吧,毕竟二者很相似,在实际应用的很多场景中确实可以互相替代。但是把double数据直接保存成float的显然是错误的,首先这可能会丢失一部分精度,而且还可能会造成数据溢出。我一个小数点10多位的double,你给我用float保存,结果取值的时候就只剩下7位了,虽然大部分情况下不会造成严重后果,但这在本质上是错误的,即使真这么做了,也只能说是一种妥协。

方法二:转成String类型保存

比较机灵的人可能这么想,我先用String.valueOf(double)把double数据转成String进行保存,在取出来的时候再用Double. parseDouble(String)进行转换不就行了?       这种做法还算是靠谱,至少在使用中不会出现溢出和损失精度之类的问题,但也不完美,因为Double和String的互相转换这2个方法是有一定的性能损耗的(当然还不至于产生ANR等问题)。那么有没有更好的办法?

方法三:转化为raw long bits进行保存,取值的时候再转化为double    

Double类中有这样一个方法:

 

public static long doubleToRawLongBits(double value)

该方法返回根据IEEE754浮点“双精度格式”位布局,不是非数字(NaN)值,返回指定浮点值的表示。它包括以下要点:

  • 如果参数为正无穷大,其结果是 0x7ff0000000000000L.
  • 如果参数为负无穷大,其结果是 0xfff0000000000000L.
  • 如果参数为NaN,那么结果是长整型表示实际NaN值。doubleToLongBits方法不同,doubleToRawLongBits不垮所有的位模式NaN编码为一个单一的“规范”NaN值。

这样一来,就可以完整的把double进行保存了。由于转换后的数据跟原来的double数据长度一致,因为完全不必担心会有精度损失或者溢出的问题。通过Double.longBitsToDouble(long value)方法则可以得到原来的double数据。

所以,我们可以用如下2个方法,实现在SharedPreferences里保存和获取double数据了:

 

static SharedPreferences.Editor putDouble(final SharedPreferences.Editor edit, final String key, final double value) {
        return edit.putLong(key, Double.doubleToRawLongBits(value));
    }
    static double getDouble(final SharedPreferences prefs, final String key, final double defaultValue) {
        if ( !prefs.contains(key))
            return defaultValue;
        return Double.longBitsToDouble(prefs.getLong(key, 0));
    }