为了提高对SharedPreferences.Editor的调用的可读性,我想使用每次需要新的SharedPreferences.Editor时执行'getSharedPreferences.edit()'的Kotlin变量.最初我打算使用这样的东西:
val editPreferences: SharedPreferences.Editor = Application.getSharedPreferences("preferences", Context.MODE_PRIVATE).edit()
Run Code Online (Sandbox Code Playgroud)
但后来我被告知,'editPreferences'将保留对同一编辑器的引用,当我每次调用'editPreferences'时我真正希望它创建一个新的编辑器.
如果使用自定义getter,每次都会返回一个新的编辑器吗?像这样的东西:
val editPreferences: SharedPreferences.Editor
get() = Application.getSharedPreferences("preferences", Context.MODE_PRIVATE).edit()
Run Code Online (Sandbox Code Playgroud)
仍在使用Kotlin并且不确定get()方法是否会引用编辑器而不是创建新的编辑器.
您可以更进一步,使用委托包装属性,利用元数据上的变量名称.
class SomeActivity : SomeBaseActivity {
// Declare property the with key "myImportantNumber"
// and default value 10
var myImportantNumber by preference(10)
//how to access the property
fun isMyImportantNumberReallyHight() = myImportantNumber > 100
//how to edit the property
fun incrementMyImportantNumber(times:Int){
myImportantNumber = myImportantNumber + times
}
}
Run Code Online (Sandbox Code Playgroud)
委托保留一些首选项管理器的实例,并使用属性上的元数据来获取和保存共享首选项的值.
class DelegatedPreference<T>(val default: T, val contextProvider:()-> Context) {
val manager by lazy { PreferencesManager(contextProvider()) }
@Suppress("UNCHECKED_CAST")
operator fun getValue(thisRef: Any?, prop: KProperty<*>): T {
return manager.get(prop.name, default)
}
operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: Any) {
manager.save(prop.name, value)
}
class TypeNotImplementedException(val propName:String) : Exception("Type of ${propName} is not implemented on DelegatedPreference and thus invalid")
}
Run Code Online (Sandbox Code Playgroud)
一点扩展方法:
fun <T> Activity.preference(default:T):DelegatedPreference<T>{
return DelegatedPreference(default, {this})
}
Run Code Online (Sandbox Code Playgroud)
这允许我们改变这个:
var myImportantNumber by DelegatedPreference(10, {this})
Run Code Online (Sandbox Code Playgroud)
通过更可读的东西:
var myImportantNumber by preference(10)
Run Code Online (Sandbox Code Playgroud)
在这里我所谓的PreferencesManager(对不起,我没有提出一个更好的名字)做繁重的工作,.edit()每次需要改变一个属性时调用.它看起来像:
public class PreferencesManager(context: Context) {
private val preferences = getSharedPreferences(context)
companion object Utils {
public val APP_PREFERENCES: String = "APP_PREFERENCES"
fun getSharedPreferences(context: Context): SharedPreferences {
return context.getSharedPreferences(APP_PREFERENCES, Context.MODE_PRIVATE)
}
}
public fun save(label:String, elem:Any){
when(elem){
is Int -> preferences.edit().putInt(label, elem).apply()
is String -> preferences.edit().putString(label, elem).apply()
is Float -> preferences.edit().putFloat(label, elem).apply()
is Boolean -> preferences.edit().putBoolean(label, elem).apply()
else -> throw DelegatedPreference.TypeNotImplementedException(label)
}
}
@Suppress("UNCHECKED_CAST", "IMPLICIT_CAST_TO_ANY")
public fun <T> get(label:String, default:T):T = when(default){
is Int -> preferences.getInt(label, default)
is String -> preferences.getString(label, default)
is Float -> preferences.getFloat(label, default)
is Boolean -> preferences.getBoolean(label, default)
else -> throw DelegatedPreference.TypeNotImplementedException(label)
} as T
}
Run Code Online (Sandbox Code Playgroud)
这里有很大的改进空间(比如参数化首选项名称而不是硬编码,给出了序列化其他类型的扩展点等),但总体思路仍然存在.
第二个属性声明满足您的需求:它有一个自定义 getter,因此获取属性值将始终执行 getter ,并且不存储该值(该属性没有支持字段)。
您可能对等号 in 感到困惑get() = ...,但它只是getter 等效形式的单表达式简写:
val editPreferences: SharedPreferences.Editor
get() {
return Application
.getSharedPreferences("preferences", Context.MODE_PRIVATE)
.edit()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
593 次 |
| 最近记录: |