Search code examples
androidkotlinandroidx

How to read and write SharedPreferences when use "androidx.preference:preference-ktx:1.1.1" with Kotlin?


Normally, I use Code A or Code B to read or write SharedPreferences.

At present, I update my project to use "androidx.preference:preference-ktx:1.1.1" with Kotlin.

Is there a better way to read and write SharedPreferences when I use "androidx.preference:preference-ktx:1.1.1" with Kotlin ?

Code A

SharedPreferences prfs = getSharedPreferences("AUTHENTICATION_FILE_NAME", Context.MODE_PRIVATE);
String Astatus = prfs.getString("Authentication_Status", "");

Code B

SharedPreferences preferences = getSharedPreferences("AUTHENTICATION_FILE_NAME", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("Authentication_Id",userid.getText().toString());
editor.putString("Authentication_Password",password.getText().toString());
editor.putString("Authentication_Status","true");
editor.apply();

Solution

  • If you're not using a dependency injection tool such as hilt, koin, etc, it's better to make a singleton class which manages preferences values to not to obtain a SharedPreferences object each time you want to read or write a value. SingletonHolder helps you make a singleton class with parameters in a thread-safe manner.

    Otherwise, if you're using a dependency injection tool in your project, you can skip the singleton part of the below solution and let the DI tool do it.


    PrefManager.kt

    import android.content.Context
    
    class PrefManager private constructor(context: Context) {
    
        // ------- Preference Variables
    
        var authenticationId: String?
            get() = pref.getString("KEY_AUTHENTICATION_ID", null)
            set(value) = pref.edit { putString("KEY_AUTHENTICATION_ID", value) }
    
        var authenticationStatus: Boolean
            get() = pref.getBoolean("KEY_AUTHENTICATION_STATUS", false)
            set(value) = pref.edit { putBoolean("KEY_AUTHENTICATION_STATUS", value) }
    
        // ---------------------------------------------------------------------------------------------
    
        private val pref = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
    
        fun clear() = pref.edit { clear() }
    
        companion object : SingletonHolder<PrefManager, Context>(::PrefManager) {
            private const val FILE_NAME = "AUTHENTICATION_FILE_NAME"
        }
    }
    

    SingletonHolder.kt

    open class SingletonHolder<out T, in A>(private val constructor: (A) -> T) {
    
        @Volatile
        private var instance: T? = null
    
        fun getInstance(arg: A): T {
            return when {
                instance != null -> instance!!
                else -> synchronized(this) {
                    if (instance == null) instance = constructor(arg)
                    instance!!
                }
            }
        }
    }
    

    Usage:

    Now we can read a value like the following:

    val authenticationId = PrefManager.getInstance(context).authenticationId
    

    and in order to write:

    PrefManager.getInstance(context).authenticationId = "SOME VALUE"