Last active
July 26, 2023 10:19
-
-
Save mhrohani1385/2c6bdd3c2ba899ec67792b9b4a87aa77 to your computer and use it in GitHub Desktop.
rememberSavable alternative wiht a useful feature for saving in Shared Preferences from a Composable scope. Eesy to use (like usage.kt) !
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ShardPreferencesHandler<T>( | |
private val `class`: Class<T>, | |
context: Context, | |
private val initValue : T?, | |
private val key: String? = null, | |
private val addNameToKey: Boolean = false | |
) { | |
enum class Type(val theClass: KClass<*>) { | |
Float(kotlin.Float::class), | |
String(kotlin.String::class), | |
Long(kotlin.Long::class), | |
Int(kotlin.Int::class), | |
Boolean(kotlin.Boolean::class) | |
} | |
private var type: Type? = null | |
init { | |
kotlin.run { | |
for (typeFor in Type.values()) { | |
Log.d("CheckType", typeFor.name + " :: " + typeFor.theClass) | |
if (checkType(typeFor.theClass)) { | |
type = typeFor | |
} | |
} | |
if (type == null) { | |
throw Exception("Type : (${`class`}) isn't supported with preferences. Only (String, Float, Long, Int, Boolean) are supported types") | |
} | |
} | |
} | |
private lateinit var calculatedKey: String | |
private val sharedPreferences by lazy { | |
context.applicationContext.getSharedPreferences("MAIN", Context.MODE_PRIVATE) | |
} | |
@Suppress("UNCHECKED_CAST") | |
private fun getMainValue(key: String?): T? { | |
if (!::calculatedKey.isInitialized && key != null) { | |
this.calculatedKey = key | |
} | |
return when (type!!) { | |
Type.String -> sharedPreferences.getString(calculatedKey, initValue as String?) | |
Type.Long -> sharedPreferences.getLong( | |
calculatedKey, | |
initValue?.let { it as Long } ?: Long.MIN_VALUE) | |
Type.Float -> sharedPreferences.getFloat( | |
calculatedKey, | |
initValue?.let { it as Float } ?: Float.MIN_VALUE) | |
Type.Int -> sharedPreferences.getInt( | |
calculatedKey, | |
initValue?.let { it as Int } ?: Int.MIN_VALUE) | |
Type.Boolean -> sharedPreferences.getBoolean( | |
calculatedKey, | |
initValue?.let { it as Boolean } ?: false) | |
} as T? | |
} | |
private fun checkType(t: KClass<*>): Boolean = | |
`class` == t.javaObjectType | |
private fun setMainValue(key: String?, value: T?) { | |
if (!::calculatedKey.isInitialized && key != null) { | |
this.calculatedKey = key | |
} | |
sharedPreferences.edit { | |
if (value == null) { | |
remove(calculatedKey) | |
} else { | |
when (type) { | |
Type.String -> putString(calculatedKey, value as String) | |
Type.Long -> putLong(calculatedKey, value as Long) | |
Type.Float -> putFloat(calculatedKey, value as Float) | |
Type.Int -> putInt(calculatedKey, value as Int) | |
Type.Boolean -> putBoolean(calculatedKey, value as Boolean) | |
else -> {} | |
} | |
} | |
apply() | |
} | |
} | |
// Delegates | |
operator fun getValue( | |
thisRef: T?, | |
property: KProperty<*> | |
): T? { | |
return this.getMainValue(getKey(key, property.name, addNameToKey)) | |
} | |
// Delegates | |
operator fun setValue( | |
thisRef: T?, | |
property: KProperty<*>, | |
value: T? | |
) { | |
this.setMainValue(getKey(key, property.name, addNameToKey), value) | |
} | |
private fun getKey(key: String?, propertyName: String, addNameToKey: Boolean) = | |
if (key != null) { | |
if (addNameToKey) { | |
key + "_" + propertyName | |
} else { | |
key | |
} | |
} else { | |
propertyName | |
} | |
companion object { | |
inline operator fun <reified T : Any> invoke( | |
context: Context, | |
initValue: T?, | |
key: String? = null, | |
addNameToKey: Boolean = false | |
) = | |
ShardPreferencesHandler( | |
T::class.java.kotlin.javaObjectType, | |
context, | |
initValue, | |
key, | |
addNameToKey | |
) | |
} | |
} | |
inline fun <reified T : Any> Context.rememberPreference( | |
initialValue: T, | |
key: String, | |
addNameToKey: Boolean = false | |
): Defs.ShardPreferencesHandler<T> = Defs.ShardPreferencesHandler(context = this, initialValue, key, addNameToKey) | |
@Deprecated( | |
"It makes conflate for two variable with same name. if you are using this make variable names different", | |
replaceWith = ReplaceWith("Context.rememberPreference(initialValue: T? = null, key: String, addNameToKey : Boolean = false)") | |
) | |
@Composable | |
inline fun <reified T : Any> Context.rememberPreference( | |
initialValue: T | |
): Defs.ShardPreferencesHandler<T> = Defs.ShardPreferencesHandler(context = this, initialValue) | |
/** | |
* T must be primitive | |
* | |
*/ | |
@Composable | |
inline fun <reified T: Any,reified O : Any> rememberPreferenceAsState( | |
initialValue: O, | |
key: String, | |
crossinline convert: @DisallowComposableCalls (valueToConvert: T) -> O, | |
crossinline reverseConvert: @DisallowComposableCalls (valueToConvert: O) -> T | |
) : MutableState<O> { | |
val context = LocalContext.current | |
val preferencesHandler = remember { | |
context.rememberPreference( | |
key = key, | |
initialValue = reverseConvert(initialValue) | |
) | |
} | |
var valueOfPreference by preferencesHandler | |
val valueState = remember { | |
mutableStateOf(convert(valueOfPreference)) | |
} | |
val updatedValue by valueState | |
// NOT LaunchedEffect(key1 = valuePreference) | |
LaunchedEffect(key1 = updatedValue, block = { | |
valueOfPreference = reverseConvert(updatedValue) | |
}) | |
return valueState | |
} | |
@Composable | |
inline fun <reified T: Any> rememberPreferenceAsState( | |
initialValue: T, | |
key: String | |
) : MutableState<T> = rememberPreferenceAsState(initialValue = initialValue, key = key, convert = { it }, reverseConvert = { it }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
fun Content() { | |
var isTourchEnabled by rememberPreferenceAsState(true) // rememberPreferenceAsState(true, key = "IS_TOURCH_ENABLED") // Returns Mutable State | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment