40

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

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

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

4

5 回答 5

51

您可以为它使用一个简单的字符串,然后使用 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

于 2013-08-14T13:09:05.587 回答
44

这与企业 Java 开发人员在将枚举持久保存到数据库时面临的问题相同。现有答案的问题在于它们很脆弱并且不适合重构。这就是为什么(底部有替代方案。)

使用枚举toString()valueOf()方法意味着不能重命名枚举值。假设我有一个带有值和的VehicleType枚举。如果我将字符串“TRUCK”存储为首选项值,然后在我的应用程序的下一个版本中重命名为,则存储的字符串不再有意义并且会抛出.CARTRUCKVehicleType.TRUCKVehicleType.PICKUP_TRUCKvalueOf()IllegalArgumentException

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

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

于 2014-04-09T02:06:02.033 回答
13

您可以将枚举与整数相关联并存储简单的 int,如下所示:

将 Int 转换为 Java 中的枚举(第二个答案)- 也可以采用同样的方式enumToInt

于 2013-02-07T12:12:05.710 回答
3

考虑到上述所有选项,我决定使用另一种解决方案来解决这个问题。

我只需要一组值,没有任何逻辑。在这种情况下,可以使用这样的工具,@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();
  }

这是官方文档

于 2017-12-14T23:00:10.103 回答
1

这是我为此编写的一个不错的实用程序类。它非常通用,可以满足广泛的需求。

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 <T> The type of Enum stored
     * @return The Enum stored as a preference with the given key
     */
    public static <T extends Enum<T>> Enum getEnum(final Context context, final String key, final Class<T> 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;
    }
}
于 2019-09-04T13:53:52.303 回答