Я добавил некоторую полезность в Tool.kt, и метод A, и метод B могут работать хорошо.
Я думаю, что метод B будет храниться в памяти при запуске приложения, даже если я никогда не вызываю fun <T> preference(context: Context, name: String, default: T)
Я думаю, что метод А выделяет память только при вызове DelegatesExt.preference(this,"ZipCode",100L)
Поэтому я считаю, что метод А лучше метода В, верно?
Способ 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() } }
Я думаю, что метод B будет храниться в памяти, когда я запустил приложение, даже если я никогда не вызываю
fun <T> preference(context: Context, name: String, default: T)
Что именно он сохранит в памяти?
Нет, методы одинаковы, кроме использования при вызове в Котлин. Но на самом деле, preference
метода B находится внутри класса ToolKt
которое вы можете увидеть, если попытаетесь вызвать его из Java.
Зачем определять одну из функций preference
вместо прямого использования конструктора Preference
? Конструкторы Kotlin не имеют проблем с выводами типа, такими как Java.
Метод A будет выделять object DelegatesExt
во время инициализации статического класса – как только вы ссылаетесь на DelegatesExt
в своем коде, потому что object
в Kotlin является singleton с ленивой инициализацией.
Затем, когда вы назовете DelegatesExt.preference(...)
, он выделит ваш объект Preference<T>
. Кстати, он будет выделять новый экземпляр для каждого вызова, что не является хорошей идеей.
Затем, когда вы getValue
или setValue
, будут выделены SharedPreferences
(один раз только для экземпляра Preference<T>
).
Метод B не выделяет избыточный object DelegatesExt
, а Preference<T>
также будет выделен для каждого вызова метода. Это будет скомпилировано для эффективного использования того же кода, что и класс со статическим методом в Java.
Но Preference<T>
не будет выделено перед вызовом метода preference
(в обоих случаях).
Короче говоря, оба варианта почти одинаковы, за исключением object DelegatesExt
который выделяется или нет. Но стоит прекратить выделение нового Preference<T>
для каждого вызова метода preference
.