|
1 | 1 | package me.jfenn.androidutils.prefs |
2 | 2 |
|
3 | 3 | import android.content.SharedPreferences |
| 4 | +import java.lang.reflect.ParameterizedType |
| 5 | +import java.lang.reflect.Type |
| 6 | +import java.lang.reflect.WildcardType |
| 7 | + |
| 8 | +/** |
| 9 | + * Edits the calling SharedPreferences instance through the provided |
| 10 | + * lambda and applies changes after completion |
| 11 | + */ |
| 12 | +inline fun SharedPreferences.edit(block: SharedPreferences.Editor.() -> Unit) { |
| 13 | + val editor = edit() |
| 14 | + editor.block() |
| 15 | + editor.apply() |
| 16 | +} |
| 17 | + |
| 18 | +abstract class TypeReference<T> : Comparable<TypeReference<T>> { |
| 19 | + val type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments.first() as ParameterizedType |
| 20 | + val arg = (type.actualTypeArguments.first() as WildcardType).upperBounds.first() as Class<*> |
| 21 | + override fun compareTo(other: TypeReference<T>) = 0 |
| 22 | +} |
4 | 23 |
|
5 | 24 | inline operator fun <reified T> SharedPreferences.get(key: String) : T? { |
| 25 | + return when(T::class) { |
| 26 | + List::class, MutableList::class -> { |
| 27 | + val itemType = object : TypeReference<T>() {}.arg |
| 28 | + val list = ArrayList<Any>() |
| 29 | + val size = getInt("${key}-length", -1) |
| 30 | + |
| 31 | + if (size == -1) |
| 32 | + return null |
| 33 | + |
| 34 | + for (i in 0 until size) { |
| 35 | + val itemKey = "${key}#${i}" |
| 36 | + when (itemType) { |
| 37 | + Boolean::class.java -> getPrimitive<Boolean>(itemKey) |
| 38 | + Float::class.java -> getPrimitive<Float>(itemKey) |
| 39 | + Int::class.java -> getPrimitive<Int>(itemKey) |
| 40 | + Long::class.java -> getPrimitive<Long>(itemKey) |
| 41 | + String::class.java -> getPrimitive<String>(itemKey) |
| 42 | + else -> null |
| 43 | + }?.let { |
| 44 | + list.add(it) |
| 45 | + } |
| 46 | + } |
| 47 | + |
| 48 | + return list as? T |
| 49 | + } |
| 50 | + else -> getPrimitive(key) |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +inline fun <reified T> SharedPreferences.getPrimitive(key: String) : T? { |
6 | 55 | if (!this.contains(key)) |
7 | 56 | return null |
8 | 57 |
|
9 | | - return when(T::class) { |
| 58 | + return when (T::class) { |
10 | 59 | Boolean::class -> this.getBoolean(key, false) as T |
11 | 60 | Float::class -> this.getFloat(key, 0f) as T |
12 | 61 | Int::class -> this.getInt(key, 0) as T |
13 | 62 | Long::class -> this.getLong(key, 0) as T |
14 | 63 | String::class -> this.getString(key, "") as T |
15 | | - Set::class -> this.getStringSet(key, HashSet()) as T |
| 64 | + Set::class, HashSet::class -> { |
| 65 | + this.getStringSet(key, HashSet()) as T |
| 66 | + } |
16 | 67 | else -> null |
17 | 68 | } |
18 | 69 | } |
19 | 70 |
|
20 | | -inline operator fun <reified T> SharedPreferences.set(key: String, value: T?) { |
21 | | - val editor = this.edit() |
| 71 | +inline operator fun <reified T> SharedPreferences.set(key: String, value: T?) = edit { |
| 72 | + when (T::class) { |
| 73 | + List::class, MutableList::class -> { |
| 74 | + val itemType = object : TypeReference<T>() {}.arg |
| 75 | + val list = value as List<*> |
22 | 76 |
|
| 77 | + putInt("${key}-length", list.size) |
| 78 | + list.forEachIndexed { index, item -> |
| 79 | + val itemKey = "${key}#${index}" |
| 80 | + when (itemType) { |
| 81 | + Boolean::class.java -> putPrimitive(itemKey, item as? Boolean) |
| 82 | + Float::class.java -> putPrimitive(itemKey, item as? Float) |
| 83 | + Int::class.java -> putPrimitive(itemKey, item as? Int) |
| 84 | + Long::class.java -> putPrimitive(itemKey, item as? Long) |
| 85 | + String::class.java -> putPrimitive(itemKey, item as? String) |
| 86 | + else -> null |
| 87 | + } |
| 88 | + } |
| 89 | + } |
| 90 | + else -> putPrimitive(key, value) |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +inline fun <reified T> SharedPreferences.Editor.putPrimitive(key: String, value: T?) { |
23 | 95 | if (value == null) |
24 | | - editor.remove(key) |
| 96 | + remove(key) |
25 | 97 | else when(T::class) { |
26 | | - Boolean::class -> editor.putBoolean(key, value as Boolean) |
27 | | - Float::class -> editor.putFloat(key, value as Float) |
28 | | - Int::class -> editor.putInt(key, value as Int) |
29 | | - Long::class -> editor.putLong(key, value as Long) |
30 | | - String::class -> editor.putString(key, value as String) |
31 | | - Set::class -> editor.putStringSet(key, value as Set<String>) |
| 98 | + Boolean::class -> putBoolean(key, value as Boolean) |
| 99 | + Float::class -> putFloat(key, value as Float) |
| 100 | + Int::class -> putInt(key, value as Int) |
| 101 | + Long::class -> putLong(key, value as Long) |
| 102 | + String::class -> putString(key, value as String) |
| 103 | + Set::class, HashSet::class -> { |
| 104 | + putStringSet(key, value as Set<String>) |
| 105 | + } |
32 | 106 | } |
33 | | - |
34 | | - editor.apply() |
35 | 107 | } |
0 commit comments