Спасите enum к SharedPreference

Я задавался вопросом, что общепринятая методика использует экономить Enum , чтобы SharedPrefereces ? В настоящее время я использую gson , чтобы преобразовать enum, чтобы Натянуть, и затем спасти его, чтобы SharedPrefereces .

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

Я задавался вопросом, действительно ли это - хороший путь? Есть ли какой-либо лучший путь?

28
nl ja de

4 ответы

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

Here is the sample code which you can see how does it works. https://github.com/jiahaoliuliu/SavingEnumToSharedPreferences

41
добавлено
Я использовал бы myEnum.name() вместо .toString() , поскольку это может быть отвергнуто
добавлено автор Fernando Gallego, источник
Стоимость последовательности Enum может быть изменена ProGuard, еще хуже, это будет отличаться через сборки конечных версий.
добавлено автор Sokolov, источник

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

Используя enum's toString() и valueOf() методы означают, что перечисление значений не может быть переименовано. Предположим, что у меня есть VehicleType enum с ценностями АВТОМОБИЛЬ и ГРУЗОВИК . Если я храню последовательность "ГРУЗОВИК" как предпочтительная стоимость и затем переименовываю VehicleType. ГРУЗОВИК , чтобы VehicleType. PICKUP_TRUCK в следующей версии моего приложения, сохраненная последовательность больше не имеет смысл, и valueOf() бросит IllegalArgumentException .

Используя средства ординала стоимости, что ценности enum не могут быть переупорядочены или больше не будут совпадать ваши сохраненные ценности. Этот сценарий возможно хуже, потому что ваше приложение продолжит бежать, но может вести себя неожиданными способами, делая проблему трудной разыскать, как только это наконец замечено и вероятно невозможное исправить. То же самое верно для добавления новой стоимости где угодно, но конца. Если бы я добавил новое МОТОЦИКЛ стоимость наверху, АВТОМОБИЛЬ сохраненный, когда его ординал (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;
    }
}

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

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

34
добавлено
@WayneJ, Если enum' s имя или порядковый wasn' t написанный постоянной памяти и умер с вашим VM, я соглашусь. , Но , когда ваше приложение хранит предпочтение, оно "пропускает" стоимость в том смысле, что версия вашего приложения, которое написало стоимость, может не быть версией вашего приложения, которое читает его позднее. Вы, конечно, могли повторно учесть свой код, чтобы использовать этот подход позже, но как вы сказал, тогда необходимо будет не забыть делать это..., и другие разработчики должны были бы знать, чтобы повторно учесть его... и также помнить к. It' s личное предпочтение, но я следовал бы за этим простым образцом с начала.
добавлено автор spaaarky21, источник
Я don' t видят, как предыдущий пример - ' fragile'. это не делает ' leak' Последовательность используется предпочтениями. Почему can' t более простая версия быть преобразованным в эту более сложную версию, если/когда названия перечисления должны быть изменены? Я довольно плохо знаком с Явой, я пропускаю что-то? Я предполагаю, что единственный недостаток - то, что необходимо было бы помнить, что рефакторинг необходим, используя первый пример...
добавлено автор WayneJ, источник

Вы можете assotiate ваш enums с целыми числами и хранить простой интервал, смотреть это:

Cast Int to enum in Java (second answer) - also in same way you can do enumToInt

8
добавлено
как выбор enum может быть сохранен также как Последовательность если использование Enum.name() вместо порядкового ()
добавлено автор pratt, источник

Рассматривая все варианты выше я решил использовать другое решение для проблемы.

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

Решение безопасно повторно учесть и с точки зрения заказа имен и переменных переменных. Единственная вещь, которая не должна быть изменена - фактические значения. Однако инструменты рефакторинга по умолчанию не попросят, чтобы вы изменили их в случае переименования, таким образом, не будет настолько легко сделать его просто автоматически (и @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();
  }

And here is the official doc

2
добавлено
Mobile Dev Jobs — вакансии и аналитика
Mobile Dev Jobs — вакансии и аналитика
6 187 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin и т.д. ВАЖНО: Правила публикации и правила канала: Ссылка – https://telegra.ph/Pravila-oformleniya-vakansij-i-rezyume-11-09-2

Android Developers
Android Developers
4 476 участник(ов)

Общаемся на темы, посвященным Android-разработке, SDK, Kotlin, Realm и т.д.

Android Architecture
Android Architecture
2 186 участник(ов)

Русскоязычный чат по архитектуре в андроид приложениях. Подробнее: http://telegra.ph/Android-Architecture-12-24

rus-speaking/android
rus-speaking/android
1 705 участник(ов)

Основной чат по Android разработке (вопрос-ответ). ПРАВИЛА: bit.ly/andr-rules. NEWS: bit.ly/AnrdResId ЧАТЫ: Основной: bit.ly/andr-main IDE, сборка, Git, сервисы: bit.ly/andr-tools Оффтоп: bit.ly/andr-offtop Конференции, события: bit.ly/andr-events Вакансии, найм: bit.ly/andr-job Архитектура: bit.ly/andr-patterns Rx: bit.ly/andr-rx Тестирование: bit.ly/andr-test Kotlin: bit.ly/andr-kotlin Хаmarin: bit.ly/andr-xamarin За мат, спам, агрессию, предложения о работе, оффтоп в этом канале - бан на сутки и более ☢☢☢

Android Dev Подкаст
Android Dev Подкаст
1 325 участник(ов)

Комната для обсуждения Android Dev подкаста apptractor.ru/AndroidDev/ Общее обсуждение Android: https://t.me/android_ru Остальные чаты про Android: http://t.me/devChats Наши новости https://t.me/androiddevpodcast_news

Android Guards
Android Guards
602 участник(ов)

Обсуждение любых вопросов касающихся безопасности Android. - Защита системы и приложений - Уязвимости и эксплойты - Вредоносное ПО - Копание в кишках системы и приложений (RE)

Android JOB
Android JOB
466 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению Android (full-time, part-time, remote и разовые подработки)

AndroidDev :: Разработка. It's Android time now!
AndroidDev :: Разработка. It's Android time now!
458 участник(ов)

It's Android time now! Чат разработчиков Android. Вакансии, резюме и информацию о митапах размещать можно. Публикацию скрытой и явной рекламы ваших каналов и сайтов после получения разрешения от @olegushakov

Aandroid Talks!
Aandroid Talks!
212 участник(ов)

Чат об общих вопросах по ОС Android. Чат для разработки под андроид - pro.android: https://t.me/joinchat/AAAAAEKIFKnmRT9cMebb9w

Android Rus
Android Rus
68 участник(ов)