54

SharedPreferences ドキュメントを見ると、次のように書かれています。

"注: 現在、このクラスは複数のプロセスでの使用をサポートしていません。これは後で追加されます。"

したがって、それ自体はスレッドセーフではないようです。しかし、commit() と apply() に関してどのような保証がなされているのでしょうか?

例えば:

synchronized(uniqueIdLock){
   uniqueId = sharedPreferences.getInt("UNIQUE_INCREMENTING_ID", 0);
   uniqueId++;
   sharedPreferences.edit().putInt("UNIQUE_INCREMENTING_ID", uniqueId).commit();
}

この場合、uniqueId が常に一意であることが保証されますか?

そうでない場合、持続するアプリケーションの一意の ID を追跡するより良い方法はありますか?

4

4 に答える 4

96

プロセスとスレッドは異なります。Android の SharedPreferences 実装はスレッドセーフですが、プロセスセーフではありません。通常、アプリはすべて同じプロセスで実行されますが、AndroidManifest.xml で構成して、サービスをアクティビティとは別のプロセスで実行することもできます。

スレッドの安全性を確認するには、AOSP の ContextImpl.java の SharedPreferenceImpl を参照してください。同期があると思われる場所に同期があることに注意してください。

private static final class SharedPreferencesImpl implements SharedPreferences {
...
    public String getString(String key, String defValue) {
        synchronized (this) {
            String v = (String)mMap.get(key);
            return v != null ? v : defValue;
        }
   }
...
    public final class EditorImpl implements Editor {
        public Editor putString(String key, String value) {
            synchronized (this) {
                mModified.put(key, value);
                return this;
            }
        }
    ...
    }
}

ただし、一意のIDの場合、取得と書き込みの間で変更したくないため、同期が必要なようです。

于 2011-01-14T20:25:13.327 に答える
7

私は同じことを考えていました-そして、スレッドセーフではないというこのスレッドに出くわしました:

Context.getSharedPreferences() と Editor.commit () の実装は、同じモニターでは同期しません。


それ以来、Android 14 のコードを調べて確認しましたが、かなり複雑です。具体的SharedPreferencesImplには、ディスクへの読み取りと書き込み時に異なるロックを使用しているようです:

  • enqueueDiskWrite()ロックオンmWritingToDiskLock
  • startLoadFromDisk()をロックしthis、スレッド ロックを起動します。SharedPreferencesImpl.this

このコードが本当に安全であるとは確信が持てません。

于 2012-08-27T12:21:27.233 に答える
4

SharedPreferences は Samsung ハンドセットでは機能しないことに注意してください。android issueを参照してください。

githubにあるシンプルなデータベース設定ストレージを実装しました。

乾杯、

于 2011-09-07T12:21:32.700 に答える
4

それで済むと思います。

同期セクション内でスリープを使用してテストし、異なるスレッドから呼び出すことができます

于 2011-01-14T16:47:54.617 に答える