マルチプロセスモードで使用するSharedPreferences
のインスタンスを定義しました。
public class Prefs {
private static SharedPreferences prefs;
private static SharedPreferences.Editor editor;
private static void init(Context context) {
prefs = context.getSharedPreferences("alaki",
Context.MODE_MULTI_PROCESS);
editor = prefs.edit();
}
// static methods to set and get preferences
}
今、私はこのクラスを別のプロセスを持つサービスで使用しており、メインのアプリケーションプロセスでも静的に使用しています。
すべて順調ですが、SharedPreferencesインスタンスに保存されているすべてのデータが削除される場合があります!
どうすればこの問題を解決できますか?
編集:最後に、IPCを使用して問題を解決しました。
documentation で説明されているように、現在複数のプロセスでSharedPreferences
に安全にアクセスする方法はありません。
注:このクラスは、複数のプロセスでの使用をサポートしていません。
MODE_MULTI_PROCESS
で何度もテストした後、3つのトライアルを共有します。
1-SharedPreferences
を各プロセスで1回初期化し、それを複数回使用します。
問題:値が期待どおりに各プロセスに反映されません。したがって、各プロセスには、SharedPreferencesの独自の値があります。
2-各putまたはgetでSharedPreferences
を初期化します。
これは実際に機能し、値はプロセス間で交換可能です。
問題:sharedprefに積極的にアクセスした後、これに説明されているように、共有設定ファイルがすべてのコンテンツとともに削除されました issue 、そして私はログでこの警告を受け取ります:
W/FileUtils﹕ Failed to chmod(/data/data/com.hegazy.multiprocesssharedpref/shared_prefs/myprefs.xml): Android.system.ErrnoException: chmod failed: ENOENT (No such file or directory)
これが問題の原因である理由を見つけることができます。
3-同期を使用して、SharedPreferences
に値を入力および取得するメソッドをロックします。
これは完全に間違っています。同期はプロセス間で機能しません。 SharedPreferences
は実際には実装で同期を使用していますが、これはスレッドの安全性のみを保証し、プロセスの安全性は保証しません。これは非常によく説明されています ここ 。
SharedPreferences自体はプロセスセーフではありません。それがおそらく理由です SharedPreferencesのドキュメント は言います
注:現在、このクラスは複数のプロセスでの使用をサポートしていません。これは後で追加されます。
commit()
メソッドを使用すると、変更が永続ストレージに保存されるため、処理が遅くなり、他のプロセスからの複数の呼び出しで競合が発生します。
ただし、このメソッドに代わる方法があります。apply()
メソッドを呼び出す必要があります。このメソッドは変更をメモリに保存し、次にディスクストレージに非同期で保存するため、信頼性が高くなります。
私はこれを組み合わせてこれを回避しました:
SharedPreferences
ファイルへの相互排他的なアクセスを提供する(たとえば、 ソケットベースのロックメカニズム を使用して)MODE_MULTI_PROCESS
フラグを使用してSharedPreferences
を再初期化するこれは問題なく動作するようですが、実際には十分にテストされていないため、完全に信頼できるかどうかはわかりません。
私が書いた実際の例を見ることができます here 。
警告:MODE_MULTI_PROCESS
はAndroid Mで非推奨になりました。将来的には機能しなくなる可能性があります。 。
静的オブジェクトとしてコンテキストオブジェクトを使用すると、アプリケーションクラスでオブジェクトを宣言しないため、コンテキストが漏洩するリスクがあることを思い出してください。
public class CustomApplication extends Application{
private Prefs prefs;
public void onCreate(){
prefs = new Prefs(this);
}
public Prefs getPrefs(){
return prefs;
}
}
どのようなコンテキストからでも設定を取得できます
((MyApplication)context.getApplicationContext()).getPrefs();
SharedPreferencesを使用するコンテンツプロバイダーを使用します。例はこちらをご覧ください: https://github.com/hamsterksu/MultiprocessPreferences