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)
}
以下のように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番目のものも大丈夫です。必要なものを使用できます。また、私が上で提供したリンクコンテンツにはもっとクールな例があります。
クラスの代わりに、オブジェクトの使用を検討してください。そのインスタンスは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}")
}
説明全体を確認してください ここ 。