Android - 共享首选项 - 上下文

Android - SharedPreferences - Context

我想使用 kotlin 为 android 中的 SharedPreference 创建一个助手 class。 不幸的是,我需要 Context,但我不想每次调用首选项时都将其设置为参数。

如果我为上下文使用伴随对象并在应用程序启动时设置它,我会收到以下错误:Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)

那么如何在每次调用首选项时获取上下文而不传递它?

 var isWorking: Boolean
    get() = getBoolean(IS_WORKING)
    set(isWorking) = setPreference(IS_WORKING, isWorking)

 private fun setPreference(key: String, value: Boolean) {
    val editor = settings.edit()
    editor.putBoolean(key, value)
    editor.commit()
}

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

您可以像下面这样创建 extension function

object PreferenceHelper {

    fun defaultPrefs(context: Context): SharedPreferences
            = PreferenceManager.getDefaultSharedPreferences(context)

    fun customPrefs(context: Context, name: String): SharedPreferences
            = context.getSharedPreferences(name, Context.MODE_PRIVATE)

    inline fun SharedPreferences.edit(operation: (SharedPreferences.Editor) -> Unit) {
            val editor = this.edit()
            operation(editor)
            editor.apply()
        }
}

编辑: Here 是这个答案的参考。您可以检查如何使用 Kotlin 技巧重构 util classes 并使用它。

编辑2:

您可以将您的助手更改为 class 并在您的 Application 中初始化它。然后你可以在任何你想用的地方使用。我认为这就是你想要做的。让我们开始吧。

class PreferenceHelper constructor(context: Context){

        fun defaultPrefs(): SharedPreferences
                = PreferenceManager.getDefaultSharedPreferences(context)

        fun customPrefs(name: String): SharedPreferences
                = context.getSharedPreferences(name, Context.MODE_PRIVATE)

        inline fun SharedPreferences.edit(operation: (SharedPreferences.Editor) -> Unit) {
                val editor = this.edit()
                operation(editor)
                editor.apply()
            }
    }

在你的申请中class:

class YourApp : Application() {

    override fun onCreate() {
        super.onCreate()
        YourApp.prefHelper = PreferenceHelper(this)
    }

    companion object {
        lateinit var prefHelper: PreferenceHelper
            private set
    }
}

您可以像下面这样在任何地方使用:

YourApp.prefHelper.defaultPrefs().edit {
    // Your shared pref operations.
}

我认为第一个更接近最佳实践,但第二个也不错。你可以使用你需要的那个。此外,我在上面提供的 link 内容中还有更多很酷的示例。

我找到了解决问题的方法。我通过保留 SharedPreferences 变量而不是上下文来解决它。

object PreferenceDao {
    private lateinit var settings: SharedPreferences

    fun init(context: Context) {
        settings = context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
    }
}

在我的 Application class 中调用了 init 函数。

考虑使用对象而不是 class。它只有一个实例,并且 SharedPreferences 可以使用应用程序的上下文进行初始化,如下所示:

object AppPreferences {
    private const val NAME = "SpinKotlin"
    private const val MODE = Context.MODE_PRIVATE
    private lateinit var preferences: SharedPreferences
    // list of app specific preferences
    private val IS_FIRST_RUN_PREF = Pair("is_first_run", false)

    fun init(context: Context) {
        preferences = context.getSharedPreferences(NAME, MODE)
    }

    /**
    * SharedPreferences extension function, so we won't need to call edit() 
        and apply()
    * ourselves on every SharedPreferences operation.
    */
    private inline fun SharedPreferences.edit(operation: 
        (SharedPreferences.Editor) -> Unit) {
        val editor = edit()
        operation(editor)
        editor.apply()
    }

    var firstRun: Boolean
        // custom getter to get a preference of a desired type, with a predefined default value
        get() = preferences.getBoolean(IS_FIRST_RUN_PREF.first, IS_FIRST_RUN_PREF.second)

        // custom setter to save a preference back to preferences file
        set(value) = preferences.edit {
            it.putBoolean(IS_FIRST_RUN_PREF.first, value)
        }
}

申请中class:

class SpInKotlinApp : Application() {
    override fun onCreate() {
        super.onCreate()
        AppPreferences.init(this)
    }
}

并且由于使用自定义 get() 和 set() 方法简化了对属性的读写,因此赋值非常容易:

if (!AppPreferences.firstRun) {
        AppPreferences.firstRun = true
        Log.d("SpinKotlin", "The value of our pref is: ${AppPreferences.firstRun}")
    }

查看完整解释here