Stringのリストがうまく永続化できない!
SharedPreferences を用いて Stringのリストを保存しようと思い下記のようにした。
// プリファレンスから、保存している値を得る val pref = getSharedPreferences("prefs", Context.MODE_PRIVATE) val stringSet = pref.getStringSet("key1", mutableSetOf()) // 適当な値をリストに追加 stringSet.add(stringSet.size.toString()) // プリファレンスに保存する pref.edit().putStringSet("key1", stringSet).apply()
ところが次のような不思議な現象に遭遇した。
- アプリの動作中は問題ない
- アプリをいったん終了し、再度立ち上げると、一番最初に記録した値のみが再現され、その後に追加した値はなかったことになっていた
どうやら、(環境により異なるが)
/data/data/(applicationId)/shared_prefs
辺りに生成される「prefs.xml」(SharedPreferencesの実態)が最初の書き込み以降更新されていないようなのだ。
putString() とか putInt() で同じようにしたときには意図したとおりに動作するのに、なぜか putStringSet() ではそのようになる。
これはバグなのだろうか?調べてみたところJavaでも同じことが起こっているようだ。
解決策として、いくつか考えてみた。
putString()等でダミーを一緒に書き込む
// プリファレンスに保存する pref.edit().putString("dummy", "dummy") pref.edit().putStringSet("key1", stringSet).apply()
これは putString() ならうまくxmlファイルの更新がかかるのでそれを利用した。冗長なデータを書き込むのであまり気分はよくない。
一旦、全てをクリアしてしまう
// プリファレンスに保存する pref.edit().clear() pref.edit().putStringSet("key1", stringSet).apply()
気分一新、全ての内容をクリアしてから再度上書きする。この場合はこれでもなんとかなってしまうのだが、このデータベースに他の情報が一緒に記録されていれば(というかその可能性は高い)目も当てられないことになる。
該当する情報だけ一旦消してから書き直す
// プリファレンスに保存する pref.edit().remove("key1").apply() pref.edit().putStringSet("key1", stringSet).apply()
該当情報だけ消して書き直す。一番角が立たない方法だろう。
remove() で消去したあと、apply() するのがポイント!これを忘れるとやっぱり最初の現象と同じになってしまう。