Сохранить enum в SharedPreference

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

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

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

Вы можете использовать простую строку для него, а затем извлечь значение с помощью метода 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

Комментарии (2)

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

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

Используя значение'с порядковым номером означает, что значения перечисляемого типа может'т быть переупорядочены или сохраненных значений уже не будет совпадать. Этот сценарий, пожалуй, хуже, потому что ваше приложение будет продолжать работать, но могут вести себя самым неожиданным образом, делая этот вопрос трудно отследить когда он'ы, наконец, заметили и, скорее всего, невозможно исправить. То же самое верно для добавления нового значения в любом месте, но итоге. Если я добавил новый мотоцикл значение в верхней части, "автомобиль", хранящиеся как его порядковый номер (0) в предыдущей версии приложения будут возвращаться мотоцикл после обновления, и "грузовик" (порядковый номер 1) стало бы "автомобиль".

Альтернативу я использую это, чтобы добавить окончательной поле enum и использовать его значение, например:

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

    private final String code;
    private static final Map 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;
    }
}

Хранить значение, используя что-то вроде предпочтения.putString("и vehicle_type наша" vehicleType.getCode ()) и получить его используя что-то вроде vehicleType = VehicleType.lookupByCode(предпочтений.метода getString (на"vehicle_type" Ну, нуль)).

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

Комментарии (5)
Решение

Вы можете assotiate ваши перечисления с целыми и хранить простые инт выглядеть так:

https://stackoverflow.com/questions/5878952/cast-int-to-enum-in-java (второй ответ) - тоже в такой же способ вы можете сделать enumToInt

Комментарии (1)

Учитывая все вышеперечисленные варианты, я решил использовать другое решение для этой проблемы.

Мне нужен только набор значений, без всякой логики на них. В этом случае можно использовать такие инструменты, как @IntDef и @StringDef вместо перечисление.

Решение является безопасным для рефакторинга как в плане имен переменных и порядок переменных. Единственная вещь, которая не должна быть изменена, - фактические значения. Однако, по умолчанию инструменты рефакторинга выиграл'т просить вас, чтобы изменить их в случае переименования, это не так легко сделать это просто автоматически (и @IntDef лучше с этой точки зрения, чем @StringDef).

  @Retention(SOURCE)
  @IntDef({NOT_REQUESTED, GIVEN, PROHIBITED})
  public @interface CustomPermission {}

  public static final int NOT_REQUESTED = -1;
  public static final int PROHIBITED = 0;
  public static final int GIVEN = 1;

  @CustomPermission
  public int getPermission() {
    return getSharedPreferences(SHARED_PREFS_FILE)
          .getInt(STATISTICS_COLLECTION_PERMISSION, NOT_REQUESTED);
  }

  public void setPermission(@CustomPermission int flag) {
    getSharedPreferences(SHARED_PREFS_FILE)
      .edit()
      .putInt(STATISTICS_COLLECTION_PERMISSION, flag)
      .apply();
  }

И вот [официальный документ doc][1]

[1]: https://developer.android.com/reference/android/support/annotation/IntDef.html на "официальные док"и

Комментарии (0)

Здесь's приятный класс utils, которую я написал для этого. Это's очень обобщенное, чтобы соответствовать широкому спектру требований.

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

public class PreferencesUtils
{
    enum StorageMode {
        /** Store enum by ordinal. */
        ORDINAL,

        /** Store enum by name. */
        NAME
    }

    private static final String PREFERENCES_NAME = "your_prefs_name";

    /**
     * Put an enum in SharedPreferences with the given key.
     * @param context The context
     * @param key The preference key
     * @param enumm The enum to store
     * @param mode The mode to store the enum - by name or ordinal
     */
    public static void putEnum(final Context context, final String key, final Enum enumm, final StorageMode mode)
    {
        final SharedPreferences sp = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
        final SharedPreferences.Editor editor = sp.edit();
        switch (mode)
        {
            default:
            case ORDINAL:
                editor.putInt(key, enumm.ordinal());
                break;
            case NAME:
                editor.putString(key, enumm.name());
                break;
        }
        editor.apply();
    }

    /**
     * Get the enum stored in SharedPreferences with the given key.
     * @param context The context
     * @param key The preference key
     * @param enumType The type of Enum stored
     * @param defaultEnumm Enum returned if a preference stored with key does not exist. Can be null.
     * @param mode The mode by which the enum was originally stored
     * @param  The type of Enum stored
     * @return The Enum stored as a preference with the given key
     */
    public static  Enum getEnum(final Context context, final String key, final Class enumType,
                                                   final Enum defaultEnumm, final StorageMode mode)
    {
        final SharedPreferences sp = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
        final T[] values = enumType.getEnumConstants();

        switch (mode)
        {
            default:
            case ORDINAL:
                final int ord = sp.getInt(key, -1);
                return ord == -1 ? defaultEnumm : values[ord];
            case NAME:
                final String name = sp.getString(key, null);
                for (final T value : values)
                {
                    if (value.name().equals(name))
                    {
                        return value;
                    }
                }
        }
        return defaultEnumm;
    }
}
Комментарии (0)