Skip to content

Instantly share code, notes, and snippets.

@astraube
Last active August 29, 2024 19:43
Show Gist options
  • Save astraube/7e84b2f63fd166a6cf6d1d3bfde2b558 to your computer and use it in GitHub Desktop.
Save astraube/7e84b2f63fd166a6cf6d1d3bfde2b558 to your computer and use it in GitHub Desktop.
package com.straucorp.datastorepreferences.delegates
/**
* @author Andre Straube - Created on 29/08/2021
*/
import android.content.Context
import android.content.SharedPreferences
import androidx.annotation.GuardedBy
import kotlinx.coroutines.*
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
/**
* Kotlin Delegate patra trabalhar com SharedPreferences
*
* Exemplo de uso:
*
* ```
* val Context.sharedPrefs by sharedPreferences(name = "app_settings")
*
* var appLaunchCount by IntPreference(
* preferences = context.sharedPrefs,
* key = "app_launch_count",
* defaultValue = 0
* )
* ```
*/
@Suppress("MissingJvmstatic")
fun sharedPreferences(
name: String,
scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
): ReadOnlyProperty<Context, SharedPreferences> {
return SharedPreferencesDelegate(name, scope)
}
/**
* Classe utilizada para facilitar o trabalho com SharedPreferences.
*/
internal class SharedPreferencesDelegate internal constructor(
private val name: String,
private val scope: CoroutineScope
) : ReadOnlyProperty<Context, SharedPreferences> {
private val lock = Any()
@GuardedBy("lock")
@Volatile
private var INSTANCE: SharedPreferences? = null
/**
* Obtem a instância do SharedPreferences.
* Uma vez executado, não cria nova instancia da classe [SharedPreferences].
* [INSTANCE] Funciona como uma variavel Singleton.
* [Context.getSharedPreferences] É executa em uma nova coroutine evitando
* bloqueio de UI e erros de [StrictMode].
*
* @param thisRef deve ser uma instancia de [Context]
* @param property não utilizado
*/
override fun getValue(thisRef: Context, property: KProperty<*>): SharedPreferences {
return INSTANCE ?: synchronized(lock) {
if (INSTANCE == null) {
// Executa em uma nova coroutine
INSTANCE = runBlocking(scope.coroutineContext) {
withContext(scope.coroutineContext) {
thisRef.applicationContext.getSharedPreferences(name, Context.MODE_PRIVATE)
}
}
}
INSTANCE!!
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment