2021年2月17日水曜日

SharedPreferencesでのcommitとapplyの違い

Androidアプリ開発での簡単なデータ保存で用いるSharedPreferences
データ保存する際に、「commit」と「apply」の二種類存在していて、どちらを使えばいいのか検討したく、違いについて調べてみた。

API仕様

書き込みが完了するまで止まって、書き込み可否を戻り値で返す。
書き込み完了まで待たず、書き込みは非同期で行われる。
commitの方が書き込み成功確認できるので良いように見えるが、公式はapply推し。
SharedPreferencesはシングルトンで、書き込みはキューに積まれ逐次処理される為、多スレッドで書き込みを実行している場合は待ちが発生する。
そのため、UIスレッドでcommitをするとANRの要因になりかねないようだ。


実装確認

SharedPreferencesはインターフェースなので、実態を確認するには
commit書き込みQueueに詰め込んだ後、書き込み完了するまでawaitで待っている。
apply書き込みQueueに詰め込むだけ。
commit、applyもenqueueDiskWrite()メソッドで共通で行っているようだ。
呼び出された順でQueuedWorkに定義されているHandlerスレッドで逐次実行されている。
QueuedWork.javaを見てみると、
commitは即Queueに詰めているが、applyは100m秒遅延実行で詰め込んでいる。
つまり、
apply後、commitを100m秒以内で行うと順番が逆転する可能性があるようだ。
なので、使用するメソッドは分けず、どちらかで一貫性を持ったせた方が良い。


結論

  • 公式に従い、UIスレッドから書き込む場合は基本的にapply
  • 「UIスレッドだからここはapply、別スレッドだからここはcommit」などの使い分けはしない方が良い。書き込みメソッドは一貫性を持たせる。
  •  ⇒逐次処理の順番が崩れる可能性がある。
  • 書き込んだものをすぐ読み出すような処理がある場合はcommit
  • ⇒書き込み完了してからでないと、データ不整合になるから
    OnSharedPreferenceChangeListenerで書き込み検知する方法もあるが、面倒...

0 件のコメント:

コメントを投稿