【问题标题】:Which one is better object or top function in Kotlin?Kotlin 中哪一个是更好的对象或顶级函数?
【发布时间】:2017-11-10 00:47:44
【问题描述】:

我在Tool.kt中放了一些实用程序,方法A和方法B都可以正常工作。

我认为方法 B 会在我启动应用程序时保留在内存中,即使我从未调用 fun <T> preference(context: Context, name: String, default: T)

我认为方法 A 只在我调用 DelegatesExt.preference(this,"ZipCode",100L) 时分配内存

所以我认为方法 A 比方法 B 更好,对吧?

方法A

object DelegatesExt {
   fun <T> preference(context: Context, name: String,   default: T) = Preference(context, name, default)
}


class Preference<T>(private val context: Context, private val name: String,
        private val default: T) {

    private val prefs: SharedPreferences by lazy {
        context.getSharedPreferences("default", Context.MODE_PRIVATE)
    }

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T = findPreference(name, default)

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putPreference(name, value)
    }

    @Suppress("UNCHECKED_CAST")
    private fun findPreference(name: String, default: T): T = with(prefs) {
        val res: Any = when (default) {
            is Long -> getLong(name, default)
            is String -> getString(name, default)
            is Int -> getInt(name, default)
            is Boolean -> getBoolean(name, default)
            is Float -> getFloat(name, default)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }

        res as T
    }

    @SuppressLint("CommitPrefEdits")
    private fun putPreference(name: String, value: T) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            is Float -> putFloat(name, value)
            else -> throw IllegalArgumentException("This type can't be saved into Preferences")
        }.apply()
    }
}

方法B

fun <T> preference(context: Context, name: String,   default: T) = Preference(context, name, default)



class Preference<T>(private val context: Context, private val name: String,
        private val default: T) {

    private val prefs: SharedPreferences by lazy {
        context.getSharedPreferences("default", Context.MODE_PRIVATE)
    }

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T = findPreference(name, default)

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putPreference(name, value)
    }

    @Suppress("UNCHECKED_CAST")
    private fun findPreference(name: String, default: T): T = with(prefs) {
        val res: Any = when (default) {
            is Long -> getLong(name, default)
            is String -> getString(name, default)
            is Int -> getInt(name, default)
            is Boolean -> getBoolean(name, default)
            is Float -> getFloat(name, default)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }

        res as T
    }

    @SuppressLint("CommitPrefEdits")
    private fun putPreference(name: String, value: T) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            is Float -> putFloat(name, value)
            else -> throw IllegalArgumentException("This type can't be saved into Preferences")
        }.apply()
    }
}

【问题讨论】:

    标签: android kotlin sharedpreferences


    【解决方案1】:

    方法 A 将在静态类初始化期间分配 object DelegatesExt - 只要您在代码中引用 DelegatesExt,因为 Kotlin 中的 object 是具有延迟初始化的单例。

    然后,当您调用DelegatesExt.preference(...) 时,它将分配您的Preference&lt;T&gt; 对象。顺便说一句,它会在每次调用时分配一个新实例,这不是一个好主意。

    然后,当您调用getValuesetValue 时,将分配SharedPreferences(每个Preference&lt;T&gt; 实例仅分配一次)。

    方法 B 不会分配冗余的object DelegatesExt,并且Preference&lt;T&gt; 也会在每个方法调用上分配。 这将被编译为与 Java 中具有静态方法的类有效地相同的代码。

    Preference&lt;T&gt; 不会在preference 方法调用之前分配(在这两种情况下)。

    长话短说,这两个选项几乎相同,除了 object DelegatesExt 是否被分配。但值得停止在每个 preference 方法调用上分配一个新的 Preference&lt;T&gt;

    【讨论】:

    • 谢谢!你的意思是这两个选项几乎相同?我可以选择任何一个!
    • 是的,它们几乎相同。方法 B 比 IMO 稍微好一点,但区别非常细微,并不重要。
    【解决方案2】:

    我认为方法 B 会在我启动应用程序时保留在内存中,即使我从未调用过 fun &lt;T&gt; preference(context: Context, name: String, default: T)

    1. 它究竟会在内存中保留什么?

    2. 不,除了在 Kotlin 中调用时使用之外,方法相同。但实际上,方法 B preference 在类 ToolKt 中,如果您尝试从 Java 中调用它,您可以看到它。

    3. 为什么要定义任一preference 函数而不是直接使用Preference 构造函数? Kotlin 构造函数没有 Java 的类型推断问题。

    【讨论】:

      猜你喜欢
      • 2019-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 2022-12-14
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      相关资源
      最近更新 更多