web-dev-qa-db-ja.com

マルチプロセスモードでSharedPreferencesを使用する

マルチプロセスモードで使用する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を使用して問題を解決しました。

20
Mousa Jafari

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は実際には実装で同期を使用していますが、これはスレッドの安全性のみを保証し、プロセスの安全性は保証しません。これは非常によく説明されています ここ

31
Ahmed Hegazy

SharedPreferences自体はプロセスセーフではありません。それがおそらく理由です SharedPreferencesのドキュメント は言います

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

6
VikramV

commit()メソッドを使用すると、変更が永続ストレージに保存されるため、処理が遅くなり、他のプロセスからの複数の呼び出しで競合が発生します。

ただし、このメソッドに代わる方法があります。apply()メソッドを呼び出す必要があります。このメソッドは変更をメモリに保存し、次にディスクストレージに非同期で保存するため、信頼性が高くなります。

3

私はこれを組み合わせてこれを回避しました:

  • 各プロセスにSharedPreferencesファイルへの相互排他的なアクセスを提供する(たとえば、 ソケットベースのロックメカニズム を使用して)
  • メモリ内キャッシュをバイパスするために使用するたびに、MODE_MULTI_PROCESSフラグを使用してSharedPreferencesを再初期化する

これは問題なく動作するようですが、実際には十分にテストされていないため、完全に信頼できるかどうかはわかりません。

私が書いた実際の例を見ることができます here

警告MODE_MULTI_PROCESSはAndroid Mで非推奨になりました。将来的には機能しなくなる可能性があります。 。

3
Sam

静的オブジェクトとしてコンテキストオブジェクトを使用すると、アプリケーションクラスでオブジェクトを宣言しないため、コンテキストが漏洩するリスクがあることを思い出してください。

public class CustomApplication extends Application{
     private Prefs prefs;

     public void onCreate(){
          prefs = new Prefs(this);
     }

     public Prefs getPrefs(){
        return prefs;
     }
}

どのようなコンテキストからでも設定を取得できます

   ((MyApplication)context.getApplicationContext()).getPrefs();
1

SharedPreferencesを使用するコンテンツプロバイダーを使用します。例はこちらをご覧ください: https://github.com/hamsterksu/MultiprocessPreferences

0
Highriser