web-dev-qa-db-ja.com

Android --SharedPreferences-コンテキスト

SharedPreferenceのヘルパークラスをAndroidでkotlinを使用して作成したい。残念ながら、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)
}
4
Thomas Klammer

以下のように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()
        }
}

編集:ここ はこの回答のリファレンスです。 Kotlinトリックでutil classesをリファクタリングして使用する方法を確認できます。

Edit2:

ヘルパーをクラスに変更し、これを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 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.
}

最初のものはベストプラクティスに近いと思いますが、2番目のものも大丈夫です。必要なものを使用できます。また、私が上で提供したリンクコンテンツにはもっとクールな例があります。

5
savepopulation

クラスの代わりに、オブジェクトの使用を検討してください。そのインスタンスは1つだけであり、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 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}")
    }

説明全体を確認してください ここ

2
lomza