Skip to content

Instantly share code, notes, and snippets.

@renaudcerrato
Last active March 22, 2018 17:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renaudcerrato/8d55a6b0da5b7cfd3e5b to your computer and use it in GitHub Desktop.
Save renaudcerrato/8d55a6b0da5b7cfd3e5b to your computer and use it in GitHub Desktop.
Android's type-safe SharedPreferences: won't throw a ClassCastException anymore if you're calling getLong() instead of getInt(). You can safely call any getter, as long as the value can be converted.
import android.content.SharedPreferences;
import java.util.Map;
import java.util.Set;
public class TypeSafeSharedPreferences implements SharedPreferences {
private final SharedPreferences sharedPreferences;
public Map<String, ?> getAll() {
return sharedPreferences.getAll();
}
public void unregisterOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
}
public boolean getBoolean(String key, boolean defValue) {
try {
return sharedPreferences.getBoolean(key, defValue);
}catch(ClassCastException e) {
return toBoolean(getAll().get(key));
}
}
public long getLong(String key, long defValue) {
try {
return sharedPreferences.getLong(key, defValue);
}catch(ClassCastException e) {
return toLong(getAll().get(key));
}
}
public boolean contains(String key) {
return sharedPreferences.contains(key);
}
public float getFloat(String key, float defValue) {
try{
return sharedPreferences.getFloat(key, defValue);
}catch(ClassCastException e) {
return (float) toDouble(getAll().get(key));
}
}
public int getInt(String key, int defValue) {
try{
return sharedPreferences.getInt(key, defValue);
}catch(ClassCastException e) {
return toInteger(getAll().get(key));
}
}
public void registerOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
}
public SharedPreferences.Editor edit() {
return sharedPreferences.edit();
}
public Set<String> getStringSet(String key, Set<String> defValues) {
return sharedPreferences.getStringSet(key, defValues);
}
public String getString(String key, String defValue) {
try {
return sharedPreferences.getString(key, defValue);
}catch(ClassCastException e) {
return String.valueOf(getAll().get(key));
}
}
public TypeSafeSharedPreferences(SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
}
static boolean toBoolean(Object value) throws ClassCastException {
if (value instanceof Boolean) {
return (Boolean) value;
} else if (value instanceof String) {
String stringValue = (String) value;
if ("true".equalsIgnoreCase(stringValue)) {
return true;
} else if ("false".equalsIgnoreCase(stringValue)) {
return false;
}
}
try {
return toDouble(value) != 0;
}catch(ClassCastException e) {
throw classCastException(value, "boolean");
}
}
static double toDouble(Object value) {
if (value instanceof Double) {
return (Double) value;
} else if (value instanceof Number) {
return ((Number) value).doubleValue();
} else if (value instanceof String) {
try {
return Double.valueOf((String) value);
} catch (NumberFormatException ignored) {
}
}
throw classCastException(value, "double");
}
static int toInteger(Object value) {
if (value instanceof Integer) {
return (Integer) value;
} else if (value instanceof Number) {
return ((Number) value).intValue();
} else if (value instanceof String) {
try {
return (int) Double.parseDouble((String) value);
} catch (NumberFormatException ignored) {
}
}
throw classCastException(value, "integer");
}
static long toLong(Object value) {
if (value instanceof Long) {
return (Long) value;
} else if (value instanceof Number) {
return ((Number) value).longValue();
} else if (value instanceof String) {
try {
return (long) Double.parseDouble((String) value);
} catch (NumberFormatException ignored) {
}
}
throw classCastException(value, "long");
}
static String toString(Object value) {
if (value instanceof String) {
return (String) value;
} else if (value != null) {
return String.valueOf(value);
}
throw classCastException(value, "string");
}
private static ClassCastException classCastException(Object value, String type) {
return new ClassCastException(value + " cannot be casted to " + type);
}
}
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertEquals;
@RunWith(AndroidJUnit4.class)
public class TestTypeSafeSharedPreferences {
private SharedPreferences mSharedPref;
@Before
public void setup() throws Exception {
Context context = InstrumentationRegistry.getTargetContext();
mSharedPref = new TypeSafeSharedPreferences(PreferenceManager.getDefaultSharedPreferences(context));
}
@Test
public void testLong() {
clear();
mSharedPref.edit().putLong("long", 42).apply();
test("long", 42);
test("long", 42L);
test("long", 42f);
}
@Test
public void testInt() {
clear();
mSharedPref.edit().putInt("int", 42).apply();
test("int", 42);
test("int", 42L);
test("int", 42f);
}
@Test
public void testFloat() {
clear();
mSharedPref.edit().putFloat("float", 42).apply();
test("float", 42);
test("float", 42L);
test("float", 42f);
}
@Test
public void testString() {
clear();
mSharedPref.edit().putString("string", "42").apply();
test("string", 42);
test("string", 42L);
test("string", 42f);
}
@SuppressWarnings("ConstantConditions")
private void test(String key, int value) {
assertEquals(value, mSharedPref.getInt(key, 0));
assertEquals((long)value, mSharedPref.getLong(key, 0));
assertEquals((float)value, mSharedPref.getFloat(key, 0));
assertEquals(value, (int) (double) Double.parseDouble(mSharedPref.getString(key, null)));
assertEquals(value != 0, mSharedPref.getBoolean(key, value == 0));
}
@SuppressWarnings("ConstantConditions")
private void test(String key, long value) {
assertEquals((int) value, mSharedPref.getInt(key, 0));
assertEquals(value, mSharedPref.getLong(key, 0));
assertEquals((float)value, mSharedPref.getFloat(key, 0));
assertEquals(value, (long) (double) Double.parseDouble(mSharedPref.getString(key, null)));
assertEquals(value != 0, mSharedPref.getBoolean(key, value == 0));
}
@SuppressWarnings("ConstantConditions")
private void test(String key, float value) {
assertEquals((int)value, mSharedPref.getInt(key, 0));
assertEquals((long)value, mSharedPref.getLong(key, 0));
assertEquals(value, mSharedPref.getFloat(key, 0));
assertEquals(value, (float) (double) Double.parseDouble(mSharedPref.getString(key, null)));
assertEquals(value != 0, mSharedPref.getBoolean(key, value == 0));
}
private void clear() {
mSharedPref.edit().clear().apply();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment