将枚举保存到SharedPreference

Che*_*eng 34 android

我想知道,什么是正在使用的常见的方法来保存EnumSharedPrefereces?目前,我正在使用gson将枚举转换为String,然后将其保存到SharedPrefereces.

    Gson gson = new Gson();
    // country is an enum.
    String json_country = gson.toJson(country);
    sharedPreferences.edit().putString(COUNTRY, json_country);
Run Code Online (Sandbox Code Playgroud)

我在想,这是一个好方法吗?有没有更好的方法?

jia*_*hao 46

您可以为它使用一个简单的String,然后使用valueOf方法提取值.这是一个例子:

public enum MyEnum {
    ENUM1, ENUM2, ENUM3, ENUM4;

    public static MyEnum toMyEnum (String myEnumString) {
        try {
            return valueOf(myEnumString);
        } catch (Exception ex) {
                // For error cases
            return ENUM1;
        }
    }
}

public void setMyEnum(Context context, MyEnum myEnum) {
    SharedPreferences sp = context.getPreferences(this.MODE_PRIVATE);
    SharedPreferences.Editor editor = sp.edit();
    editor.putString("MyEnum", myEnum.toString());
    editor.commit();
}

public MyEnum getMyEnum(Context context) {
    SharedPreferences sp = context.getPreferences(this.MODE_PRIVATE);
    String myEnumString = sp.getString("MyEnum", MyEnum.ENUM1.toString());
    return MyEnum.toMyEnum(myEnumString);
}
Run Code Online (Sandbox Code Playgroud)

以下是示例代码,您可以看到它是如何工作的. https://github.com/jiahaoliuliu/SavingEnumToSharedPreferences

  • ProGuard可能会更改枚举字符串值,更糟糕的是它在发布版本中会有所不同. (3认同)

spa*_*y21 37

这与Enterprise Java开发人员在将枚举持久保存到数据库时面临的问题相同.现有答案的问题在于它们是脆弱的而不是重构友好的.这就是原因(底部有另一种选择.)

使用枚举toString()valueOf()方法意味着无法重命名枚举值.假设我有一个VehicleType与值枚举CARTRUCK.如果我将字符串"TRUCK"存储为首选值,然后在我的应用程序的下一个版本中重命名VehicleType.TRUCKVehicleType.PICKUP_TRUCK,则存储的字符串不再有意义valueOf()并将抛出IllegalArgumentException.

使用值的序数意味着无法重新排序枚举值,或者您的存储值将不再匹配.这种情况可能会更糟,因为您的应用程序将继续运行,但可能会以意想不到的方式运行,一旦最终发现并且可能无法纠正,则难以追踪问题.在除了结尾之外的任何地方添加新值也是如此.如果我MOTORCYCLE在顶部添加了一个新值,那么CAR在应用程序的先前版本中存储为序数(0)将MOTORCYCLE在更新后返回,并且TRUCK(序数1)将变为a CAR.

我使用的替代方法是final在枚举中添加一个字段并使用其值,如下所示:

public enum VehicleType {
    CAR("C"),
    TRUCK("T");

    private final String code;
    private static final Map<String,VehicleType> valuesByCode;

    static {
        valuesByCode = new HashMap<>(values().length);
        for(VehicleType value : values()) {
            valuesByCode.put(value.code, value);
        }
    }

    VehicleType(String code) {
        this.code = code;
    }

    public static VehicleType lookupByCode(String code) { 
        return valuesByCode.get(code); 
    }

    public String getCode() {
        return code;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用类似的东西存储值,并使用类似的东西preferences.putString("vehicle_type", vehicleType.getCode())检索它vehicleType = VehicleType.lookupByCode(preferences.getString("vehicle_type", null)).

这种方法需要一些额外的代码,但在我看来,它是最强大的解决方案.

  • @WayneJ如果一个enum的名字或序号没有被写入持久性内存而死于你的VM,我会同意.**但是**当您的应用程序存储首选项时,它会"泄漏"该值,因为您编写该值的应用程序版本可能不是您以后读取该应用程序的应用程序版本.您当然可以重构您的代码以便稍后使用此方法,但就像您说的那样,您必须记住这样做......而其他开发人员必须知道重构它...并且还记得.这是个人偏好,但我宁愿从一开始就遵循这个简单的模式. (6认同)

dil*_*lix 13

你可以用整数来表示你的枚举并存储简单的int,看看这个:

在Java中将Int演绎到枚举(第二个答案) - 也可以用同样的方式enumToInt