【问题标题】:Wrap getters and setters on SharedPreferences class在 SharedPreferences 类上包装 getter 和 setter
【发布时间】:2018-06-12 09:39:55
【问题描述】:

我想重用代码并包装 getter 和 setter,因为它们具有相同的功能。

我猜应该为每种类型制作一个通用函数。

我认为维护特定属性而不是使所有通用属性更好,因为代码可以更清晰地访问这些属性。例如:MyPrefs.instance.prefOne

具有 2 个“相同”功能的 SharedPreferences 类:

import android.content.Context
import android.content.SharedPreferences

class MyPrefs private constructor() {

    companion object {
        private const val PREF_ONE = "prefOne"
        private const val PREF_TWO = "prefTwo"

        val instance = MyPrefs()
    }

    private lateinit var prefs: SharedPreferences

    fun init(context: Context) {
        this.prefs = context.getSharedPreferences(context.applicationContext.packageName
                + "." + MyPrefs::class.java.simpleName, Context.MODE_PRIVATE)
    }

    fun clear() {
        prefs.edit().clear().apply()
    }

    var prefOne: String
        get() = prefs.getString(PREF_ONE, "")
        set(prefOne) = prefs.edit().putString(PREF_ONE, prefOne).apply()

    var prefTwo: String
        get() = prefs.getString(PREF_TWO, "")
        set(prefTwo) = prefs.edit().putString(PREF_TWO, prefTwo).apply()
}

【问题讨论】:

    标签: android kotlin sharedpreferences


    【解决方案1】:

    感谢 zsmb13 的回答,我找到了一个优雅的解决方案。

    import android.content.SharedPreferences
    import kotlin.reflect.KProperty
    
    class DelegatedPreferences<T>(val prefs: SharedPreferences, private val defaultValue: T) {
    
        operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
            return getPreference(property.name, defaultValue)
        }
    
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
            setPreference(property.name, value)
        }
    
        private fun getPreference(key: String, defaultValue: T): T {
            with(prefs) {
                val result: Any = when (defaultValue) {
                    is Boolean -> getBoolean(key, defaultValue)
                    is Int -> getInt(key, defaultValue)
                    is Long -> getLong(key, defaultValue)
                    is Float -> getFloat(key, defaultValue)
                    is String -> getString(key, defaultValue)
                    else -> throw IllegalArgumentException()
                }
                @Suppress("UNCHECKED_CAST")
                return result as T
            }
        }
    
        private fun setPreference(key: String, value: T) {
            with(prefs.edit()) {
                when (value) {
                    is Boolean -> putBoolean(key, value)
                    is Int -> putInt(key, value)
                    is Long -> putLong(key, value)
                    is Float -> putFloat(key, value)
                    is String -> putString(key, value)
                    else -> throw IllegalArgumentException()
                }.apply()
            }
        }
    }
    

    具体的偏好类现在非常简单明了:

    import android.content.Context
    import android.content.SharedPreferences
    
    class MyPrefs private constructor() {
    
        companion object {
            val instance = MyPrefs()
        }
    
        val prefs: SharedPreferences by lazy {
            val context = App.instance
            context.getSharedPreferences(context.packageName + "." + MyPrefs::class.java.simpleName, Context.MODE_PRIVATE)
        }
    
        fun clear() {
            prefs.edit().clear().apply()
        }
    
        var anyProperty: String by DelegatedPreferences(prefs, "")
    }
    

    然后调用,很简单:

    MyPrefs.instance.anyProperty = "Hello!"
    Log.d("***", MyPrefs.instance.anyProperty) // Hello!
    

    【讨论】:

      【解决方案2】:

      你可以用delegated properties很好地解决这个问题。

      这是一个非常简单的示例实现,用于仅存储 String 首选项:

      class PreferencesDelegate(val context: Context, val key: String, val defaultValue: String = "") {
          private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
      
          operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
              return sharedPreferences.getString(key, defaultValue)
          }
      
          operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
              sharedPreferences.edit()
                      .putString(key, value)
                      .apply()
          }
      }
      

      您可以通过以下方式在Activity 中使用它:

      class MyActivity : AppCompatActivity() {
          var pref by PreferencesDelegate(this, "key")
      
          fun foo() {
              pref = "test"
              println(pref)
          }
      }
      

      或者使用额外的扩展函数以获得更好的语法:

      fun Activity.preference(key: String, defaultValue: String = ""): PreferencesDelegate {
          return PreferencesDelegate(this, key, defaultValue)
      }
      
      class MyActivity : AppCompatActivity() {
          var pref by preference("key")
      }
      

      有些人已经用委托更好地实现了同样的事情。例如,查看 this 博客文章以及 this 和 this 库。可能还有很多很多其他的。

      【讨论】:

      • 这是我想应用的想法。非常感谢!
      猜你喜欢
      • 2017-04-10
      • 2015-01-20
      • 1970-01-01
      • 2016-05-22
      • 2018-05-05
      • 2019-11-26
      • 2012-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多