当前位置: 首页 > 知识库问答 >
问题:

Kotlin custom get execute方法调用

印季
2023-03-14

增加对SharedReferences调用的可读性。编辑器我想使用一个Kotlin变量来执行“getSharedReferences”。每次我需要一个新的SharedReferences时,编辑()。编辑起初,我打算用这样的东西:

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

但后来我被告知,“editPreferences”将保留对同一个编辑器的引用,而我真正想要的是在每次调用“editPreferences”时创建一个新的编辑器。

如果使用自定义getter,是否每次都会返回一个新编辑器?类似这样:

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

仍然在使用静态编程语言启动和运行,并且不确定get()方法是否会保留对编辑器的引用,而不是创建一个新编辑器。

共有3个答案

毛博
2023-03-14

第二个属性声明适合您的需要:它有一个自定义的getter,因此获取属性值将始终执行getter,并且不会存储该值(该属性没有后备字段)。

您可能对get()=...中的等号感到困惑,但它只是getter等效形式的单表达式简写:

val editPreferences: SharedPreferences.Editor 
    get() { 
         return Application
              .getSharedPreferences("preferences", Context.MODE_PRIVATE)
              .edit()
    }
郭璞
2023-03-14

您可以更进一步,使用元数据上的变量名,用委托包装属性。

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

委托保留某个首选项管理器的实例,并使用属性上的元数据获取和保存共享首选项上的值。

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)(很抱歉,我没有想出一个更好的名称)完成了繁重的工作,并调用了。每次需要更改属性时编辑()。它看起来像:

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

}

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

闾丘选
2023-03-14

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

 类似资料:
  • 使用Object::exec来调用对象的方法。参数原型: Variant Object::exec(const char *method_name, Variant args ...); method_name是方法的名称,字符串类型 args参数,args是变长参数,最多可以接受10个参数 如果参数超过10个,请使用更底层的Object::call方法 使用示例 Object redis =

  • super 带块的方法调用 yield 例: foo.bar() foo.bar bar() print "hello world\n" print Class::new 语法: [表达式 `.'] 标识符 [`(' 表达式 ... [`*' [表达式]],[`&' 表达式] `)'] [表达式 `::'] 标识符 [`(' 表达式 ... [`*' [表达式]],[`&' 表达式] `)']

  • 我正在寻找一些可以让我像Mongoid那样做的事情: 基本上,包含一个模块并使用其中声明的方法。但是我得到以下错误: 这是模块代码: 下面是课程代码: 我的ruby版本是2.1.2 编辑: 我在模块中使用了这个,它工作得很好:

  • 本文向大家介绍groovy 调用方法,包括了groovy 调用方法的使用技巧和注意事项,需要的朋友参考一下 示例 请注意,如果在某些元素上不存在该方法,则在集合中混合类型时,groovy.lang.MissingMethodException可能会引发a:            

  • 本文向大家介绍Java调用方法,包括了Java调用方法的使用技巧和注意事项,需要的朋友参考一下 示例 使用反射,可以在运行时调用对象的方法。 该示例显示了如何调用String对象的方法。            

  • 普通的函数调用 普通的函数调用跟C语言中的调用方式基本上是一样的,除了多值返回的一些细微区别,见前面章节。 对象的方法调用 根据Go语言文档,对象的方法调用相当于普通函数调用的一个语法糖衣。 type T struct { a int } func (tv T) Mv(a int) int { return 0 } // value receiver func (tp *T)

  • 当你在调用某一个方法的时候,Ruby会完成下面的步骤: 找到这个方法,我们把这个过程称作方法查找(method lookup); 执行这个方法,为了执行这个方法,Ruby需要一个叫做self的伪变量; 方法的查找 要理解Ruby的方法查找,你需要了解下面两个概念:接受者(receiver)和祖先链(ancestors chain)。接受者就是方法的调用者。例如,对调用an_object.displ

  • 有没有一种方法可以调试一个被调用的方法? 此代码调用