I was wondering, what is the common method being used to save Enum
to SharedPrefereces
? Currently, I'm using gson
to convert enum to String, and then save it to SharedPrefereces
.
Gson gson = new Gson();
// country is an enum.
String json_country = gson.toJson(country);
sharedPreferences.edit().putString(COUNTRY, json_country);
I was wondering, is this a good way? Is there any better way?
You can use a simple String for it and then extract the value using the method valueOf. Here is an example:
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
This is the same problem that Enterprise Java developers face when persisting an enum to a database. The problem with the existing answers is that they are fragile and not refactoring-friendly. Here's why (with an alternative at the bottom.)
Using an enum's toString()
and valueOf()
methods means that an enum value can't be renamed. Suppose I have a VehicleType
enum with values CAR
and TRUCK
. If I store the string "TRUCK" as a preference value and then rename VehicleType.TRUCK
to VehicleType.PICKUP_TRUCK
in the next version of my app, the stored string no longer makes sense and valueOf()
will throw an IllegalArgumentException
.
Using a value's ordinal means that the enum values can't be re-ordered or your stored values will no longer match up. This scenario is arguably worse because your app will continue to run but may behave in unexpected ways, making the issue difficult to track down once it's finally noticed and likely impossible to correct. The same is true for adding a new value anywhere but the end. If I added a new MOTORCYCLE
value at the top, a CAR
stored as its ordinal (0) in the previous version of the app would come back as MOTORCYCLE
after updating, and a TRUCK
(ordinal 1) would become a CAR
.
The alternative I use is to add a final
field to the enum and use its value, like so:
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;
}
}
Store a value using something like preferences.putString("vehicle_type", vehicleType.getCode())
and retrieve it using something like vehicleType = VehicleType.lookupByCode(preferences.getString("vehicle_type", null))
.
This approach requires a little extra code but in my opinion, it's the most robust solution.
You can assotiate your enums with integers and store simple int, look this:
Cast Int to enum in Java (second answer) - also in same way you can do enumToInt
Considering all the options above I decided to use another solution for the problem.
I need only a set of values, without any logic on them. In this case, it is possible to use such tools as @IntDef
and @StringDef
instead of using enum
.
The solution is safe to refactor both in terms of variables names and variables order. The only thing that should not be changed - actual values. However, default refactoring tools won't ask you to change them in case of renaming, so it is not so easy to make it just automatically (and @IntDef
is better from this point of view than @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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With