Сохранить перечисление в SharedPreference

Мне было интересно, какой общий метод используется для сохранения Enum в SharedPrefereces ? В настоящее время я использую gson для преобразования enum в String, а затем сохраняю его в SharedPrefereces .

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

Мне было интересно, это хороший способ? Есть ли лучший способ?

Solutions Collecting From Web of "Сохранить перечисление в SharedPreference"

Вы можете ассоциировать свои перечисления с целыми числами и хранить простой int, посмотрите:

Cast Int для перечисления на Java (второй ответ) – также точно так же вы можете сделать enumToInt

Вы можете использовать простую 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); } 

Вот пример кода, который вы можете увидеть, как он работает. https://github.com/jiahaoliuliu/SavingEnumToSharedPreferences

Это та самая проблема, с которой сталкиваются разработчики Enterprise Java при сохранении перечисления в базе данных. Проблема с существующими ответами заключается в том, что они хрупкие, а не рефакторинговые. Вот почему (с альтернативой внизу).

Использование методов enum toString() и valueOf() означает, что значение перечисления не может быть переименовано. Предположим, у меня есть перечисление VehicleType со значениями CAR и TRUCK . Если я VehicleType.TRUCK строку «TRUCK» в качестве значения предпочтения, а затем переименует VehicleType.TRUCK в VehicleType.PICKUP_TRUCK в следующей версии моего приложения, сохраненная строка больше не имеет смысла, а valueOf() будет VehicleType.TRUCK VehicleType.PICKUP_TRUCK IllegalArgumentException .

Использование ординала значения означает, что значения перечисления не могут быть переупорядочены или ваши сохраненные значения больше не совпадут. Этот сценарий, возможно, хуже, потому что ваше приложение будет продолжать работать, но может вести себя непредсказуемыми способами, что затрудняет отслеживание проблемы, как только оно наконец будет замечено и, вероятно, невозможно исправить. То же самое верно для добавления нового значения где угодно, кроме конца. Если бы я добавил новое значение MOTORCYCLE вверху, CAR сохраненный в качестве его порядкового номера (0) в предыдущей версии приложения, вернется в качестве MOTORCYCLE после обновления, а TRUCK (порядковый номер 1) станет 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; } } 

Сохраните значение, используя что-то вроде preferences.putString("vehicle_type", vehicleType.getCode()) и vehicleType = VehicleType.lookupByCode(preferences.getString("vehicle_type", null)) его, используя что-то вроде vehicleType = VehicleType.lookupByCode(preferences.getString("vehicle_type", null)) .

Этот подход требует немного дополнительного кода, но, на мой взгляд, это наиболее надежное решение.