データ保存する際に、「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 件のコメント:
コメントを投稿