Kotlin自定义是否获得执行方法调用

为了增加对SharedPreferences.Editor的调用的可读性,我希望每次需要一个新的SharedPreferences.Editor时,使用一个Kotlinvariables来执行“getSharedPreferences.edit()”。 最初我打算使用这样的东西:

val editPreferences: SharedPreferences.Editor = Application.getSharedPreferences("preferences", Context.MODE_PRIVATE).edit() 

但后来我被告知,'editPreferences'将保持对同一个编辑器的引用,当我每次调用'editPreferences'时我真正想要它创build一个新的编辑器。

如果使用自定义getter,每次都会返回一个新的编辑器? 像这样的东西:

 val editPreferences: SharedPreferences.Editor get() = Application.getSharedPreferences("preferences", Context.MODE_PRIVATE).edit() 

仍然起床和Kotlin运行,我不知道如果get()方法将持有引用编辑器,而不是创build一个新的。

  • Kotlin注解处理会忽略具有相似名称的项目
  • 如何使用Kotlin与Proguard
  • Kotlin属性如何访问Java类的语法(即EditText setText)?
  • Dagger 2命名不能没有@Provides方法提供
  • 在EditText Kotlin,Android中设置文本
  • Kotlin属性:“属性的types参数必须在其接收器types中使用”
  • 如何使用Kotlin设置OnEditorActionListener
  • 在Android Studio 3.0布局编辑器中渲染错误
  • 第二个属性声明适合你的需求:它有一个自定义的getter ,因此得到的属性值将始终执行getter,并且该值不被存储(属性没有后台字段 )。

    您可能会被get() = ...的等号所迷惑,但它只是getter的等效forms的单expression式缩写 :

     val editPreferences: SharedPreferences.Editor get() { return Application .getSharedPreferences("preferences", Context.MODE_PRIVATE) .edit() } 

    如果使用自定义getter实现属性,则不会存储任何数据。 每次访问该属性时,都会执行getter的主体。

    你可以更进一步,用一个委托包装属性,使用元数据上的variables名称。

    用法

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

    代表团

    委托保留一些偏好pipe理器的实例,并使用属性上的元数据来获取并保存共享偏好的值。

     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") } 

    一些糖

    一个小扩展方法:

     fun <T> Activity.preference(default:T):DelegatedPreference<T>{ return DelegatedPreference(default, {this}) } 

    这使我们能够改变这一点:

     var myImportantNumber by DelegatedPreference(10, {this}) 

    通过更可读的东西:

     var myImportantNumber by preference(10) 

    实际得到和保存

    在这里,我所谓的PreferencesManager (对不起,我没有提出一个更好的名字)做了繁重的工作,每次需要修改属性时.edit()调用.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 } 

    在这里有很大的改进空间(比如参数化首选项名称而不是硬编码,给出序列化其他types的扩展点等),但总体思路仍然存在。

    正如热键和提到的那样,自定义的getter会导致每次都返回一个新的编辑器,这就是你想要的。

    但是,请考虑使用以下特殊function的解决scheme:

    • 内联以减less调用函数的开销
    • 扩展 ,使它看起来像一个Context类的方法,即使我们没有定义它
    • 高阶函数使我们能够在使用它之后去掉调用commit()

    宣言

     inline fun Context.editPreferences(preferenceFileName:String = "preferences",block:SharedPreferences.Editor.() -> Unit) { val editablePreferences = getSharedPreferences(preferenceFileName,Context.MODE_PRIVATE).edit() editablePreferences.block() editablePreferences.commit() } 

    用法

     Application.editPreferences() { putBoolean("SOME_BOOLEAN",true) putFloat("SOME_FLOAT",293232F) } 

    或者在很多情况下,当接收器已经是Context你可以这样做:

     editPreferences() { putBoolean("SOME_BOOLEAN",true) putFloat("SOME_FLOAT",293232F) } 

    Kotlin❤