【问题标题】:How to read and write SharedPreferences when use "androidx.preference:preference-ktx:1.1.1" with Kotlin?在 Kotlin 中使用“androidx.preference:preference-ktx:1.1.1”时如何读写 SharedPreferences?
【发布时间】:2020-07-10 09:23:35
【问题描述】:

通常,我使用代码 A 或代码 B 来读取或写入 SharedPreferences。

目前,我将我的项目更新为在 Kotlin 中使用 "androidx.preference:preference-ktx:1.1.1"

当我在 Kotlin 中使用 "androidx.preference:preference-ktx:1.1.1" 时,有没有更好的方法来读写 SharedPreferences ?

代码 A

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

代码 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();

【问题讨论】:

  • 只需将上面的代码转换为 kotlin。

标签: android kotlin androidx


【解决方案1】:

如果您没有使用诸如hiltkoin之类的依赖注入工具,最好创建一个管理首选项值的单例类,而不是获取@987654324 @object 每次要读取或写入一个值。 SingletonHolder 帮助您以线程安全的方式创建带有参数的单例类。

否则,如果您在项目中使用依赖注入工具,则可以跳过以下解决方案的单例部分,让 DI 工具来完成。


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!!
            }
        }
    }
}

用法:

现在我们可以读取如下值:

val authenticationId = PrefManager.getInstance(context).authenticationId

为了写:

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

【讨论】:

    【解决方案2】:

    无需编写自己的额外代码,对于您的代码 B sn-p,您可以使用 ktx 库完成此操作

    val preferences = getSharedPreferences("AUTHENTICATION_FILE_NAME", MODE_PRIVATE)
    preferences.edit {
       putString("Authentication_Id", userid.getText().toString())
       putString("Authentication_Password", password.getText().toString())
       putString("Authentication_Status", "true")
    }
    

    【讨论】:

      【解决方案3】:

      在您的 Pref.class 文件中将 Context 提供给构造函数。

          class Prefs constructor(
                  private val context: Context
              ) {
          
             private fun getSharedPreferences(prefsName: String) =
                  context.getSharedPreferences(prefsName, Context.MODE_PRIVATE)
          
              private val AUTH_PHONE = "auth_phone"
              private val KEY_AUTH_PHONE = "auth_phone"
              private val authPhone by lazy { getSharedPreferences(AUTH_PHONE) }
              
              var phoneNumber: String
                  get() {
                      return authPhone.getString(KEY_AUTH_PHONE, null) ?: return ""
                  }
                  set(value) {
                      authPhone.edit()
                          .putString(KEY_AUTH_PHONE, value)
                          .apply()
                  } 
      }
      

      然后你可以在你的活动中使用它。

        Pref(context).phoneNumber = "998998578086"
      

      【讨论】:

      • 如果你愿意,我可以分享 SharedPref 的完整源代码。联系我。
      【解决方案4】:

      如果您想更进一步并提高安全性,您可以并行使用encrypted sharedPreferences,因为它仅适用于 Android M 及更高版本。如果您使用 DI,这真的很容易:

      interface SharedPrefs {
          var accessToken: String?
          fun get(): SharedPreferences
      }
      
      class SimplePreferences(context: Context) : SharedPrefs {
          private val preferences: SharedPreferences =
              context.getSharedPreferences("myapp_preferences", Context.MODE_PRIVATE)
      
          override fun get(): SharedPreferences = preferences
      
          override var accessToken: String?
              get() = preferences.getString(MyApp.ACCESS_TOKEN_PREF_KEY, null)
              set(value) = preferences.edit().putString(MyApp.ACCESS_TOKEN_PREF_KEY, value)
                  .apply()
      }
      
      @TargetApi(Build.VERSION_CODES.M)
      class EncryptedSharedPrefs(val context: Context) : SharedPrefs {
      
          private var encryptedPrefs: SharedPreferences = EncryptedSharedPreferences.create(
              context,
              "myapp_encrypted_prefs",
              MasterKey.Builder(context).build(),
              EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
              EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
          )
      
          override fun get(): SharedPreferences = encryptedPrefs
      
          override var accessToken: String?
              get() = encryptedPrefs.getString(MyApp.ACCESS_TOKEN_PREF_KEY, null)
              set(value) = encryptedPrefs.edit().putString(
                  MyApp.ACCESS_TOKEN_PREF_KEY,
                  value
              ).apply()
      }
      

      koin 模块:

      single {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
               EncryptedSharedPrefs(applicationContext)
         } else
               SimplePreferences(applicationContext)
         }
      }
      

      用法:

      val sharedPrefs by inject<SharedPrefs>()
      
      // read 
      println(sharedPrefs.accessToken)
      
      // write
      sharedPrefs.accessToken = "qwerty"
      

      【讨论】:

        猜你喜欢
        • 2018-10-22
        • 2019-08-19
        • 2022-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多