在 Kotlin 中使用 "androidx.preference:preference-ktx:1.1.1" 时如何读写 SharedPreferences?
How to read and write SharedPreferences when use "androidx.preference:preference-ktx:1.1.1" with Kotlin?
通常,我使用代码A或代码B来读取或写入SharedPreferences。
目前,我更新我的项目以使用 "androidx.preference:preference-ktx:1.1.1"
和 Kotlin。
当我使用 "androidx.preference:preference-ktx:1.1.1"
和 Kotlin 时,是否有更好的读写 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();
在您的 Pref.class 文件中为构造函数提供上下文。
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()
}
}
然后你就可以在你的 activity 中使用它了。
Pref(context).phoneNumber = "998998578086"
如果你没有使用hilt
、koin
、等等依赖注入工具,最好做一个单例class 它管理首选项值,以便在每次要读取或写入值时不获取 SharedPreferences
对象。 帮助您以线程安全的方式创建带有参数的单例 class。
否则,如果您在项目中使用依赖注入工具,则可以跳过以下解决方案的单例部分,让 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"
无需编写自己的额外代码,对于您的代码 B 片段,您可以使用 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")
}
如果您想更进一步并提高安全性,可以并行使用 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()
}
对币模块:
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"
通常,我使用代码A或代码B来读取或写入SharedPreferences。
目前,我更新我的项目以使用 "androidx.preference:preference-ktx:1.1.1"
和 Kotlin。
当我使用 "androidx.preference:preference-ktx:1.1.1"
和 Kotlin 时,是否有更好的读写 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();
在您的 Pref.class 文件中为构造函数提供上下文。
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()
}
}
然后你就可以在你的 activity 中使用它了。
Pref(context).phoneNumber = "998998578086"
如果你没有使用hilt
、koin
、等等依赖注入工具,最好做一个单例class 它管理首选项值,以便在每次要读取或写入值时不获取 SharedPreferences
对象。
否则,如果您在项目中使用依赖注入工具,则可以跳过以下解决方案的单例部分,让 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"
无需编写自己的额外代码,对于您的代码 B 片段,您可以使用 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")
}
如果您想更进一步并提高安全性,可以并行使用 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()
}
对币模块:
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"