11

アプリに戻ったときにSharedPreferencesが更新されないという奇妙な問題があります。シナリオは次のとおりです。

同じ共有設定を使用する2つのプロジェクトがあります。Project1とProject2。それらは別個ですが、関連するアプリです。それらは同じキーで署名され、sharedUserIdを使用して情報を共有します。

Project1はProject2を開きます。

Project2は、SharedPreferencesファイルを取得し、次のメソッドを介して書き込みます。

Context prefsContext = c.createPackageContext(packageNameOfProject1, Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences prefs = prefsContext.getSharedPreferences(fileName, Context.MODE_PRIVATE);
SharedPreferences.editor editor = prefs.edit();
editor.putBool("bool1", value1);
editor.putBool("bool2", value2);
...
editor.putBool("boolN", valueN);
editor.apply();

それが終わったら、を呼び出してProject1に戻りfinish()ます。

次に、Project1は次のようにデータを読み取ります。

SharedPreferences prefs = getSharedPreferences(getPreferencesFileName(), Context.MODE_PRIVATE);
Boolean value1 = prefs.getBoolean(fileName, false);
Boolean value2 = prefs.getBoolean(fileName, false);
...
Boolean valueN = prefs.getBoolean(fileName, false);
Map<String, ?> mappings = prefs.getAll();
Set<String> keys = mappings.keySet();
for(String key : keys) {
  log.d(TAG, "_____");
  log.d(TAG, "Key = " + key);
  log.d(TAG, "Value = " + mappings.get(key));
}

問題は、Project1で値が更新されないことです。最後のログに基づいて、ファイルがマッピングを生成していないことがわかります。ただし、xmlが更新されていることを確認できます。アプリを強制的に停止してから再起動すると、すべてのマッピングがProject1にあります。すべての値が正しいです。ただし、ユーザーがProject2を離れるときに更新する必要があります。ここに欠けているものがあるように感じますが、それを見つけることができません。

このテーマで私が見つけたのは次のとおりです。

SharedPreferences.Editorが最初のコミット後に更新されない

SharedPreferencesの値は更新されません

私はすでにそれをしているので、これらは役に立ちません。

両方のマニフェストにWRITE_EXTERNAL_STORAGEを設定しています。fileNameは同じです(そうでない場合、アプリを再入力したときにファイルを読み取ることができません)。

編集:

競合状態に直面していると思っていeditor.commit()たのではなく、やろうとしたことに注意する必要があります。editor.apply()問題はまだ解決していません。何らかの理由で、Project1のSharedPreferenceへの古い参照が、毎回遅延読み込みしているにもかかわらず、新しい参照の代わりに使用されていると思います。

EDIT2:

OK、さらにテストして、どのIDが実行されているかを確認します。私は反対の方向を試すことにしました。

Project1では、次のことを行います。

Float testFloat (float) Math.random();
Log.d("TEST_FLOAT", "Project1: TEST_FLOAT = " + testFloat);
prefs.edit().putFloat("TEST_FLOAT", testFloat).commit();

Project2では次のことを行います。

Log.d("TEST_FLOAT", "Project2: TEST_FLOAT = " + prefs.getFloat("TEST_FLOAT", 0.0f));

次に、次のように2つの間を行ったり来たりしProject1->Project2->Project1->Project2->Project1->Project2ます。logcatの結果は次のとおりです。

Project1: TEST_FLOAT = 0.30341884
Project2: TEST_FLOAT = 0.30341884
Project1: TEST_FLOAT = 0.89398974
Project2: TEST_FLOAT = 0.30341884
Project1: TEST_FLOAT = 0.81929415
Project2: TEST_FLOAT = 0.30341884

つまり、同じファイルの読み取りと書き込みを行っています。ただし、プロジェクトで最初に開いたときのマッピングは保持されます。プロジェクトを閉じても、アプリケーションが強制的に停止されるまでマッピングは残ります。

4

3 に答える 3

24

編集:それ以来廃止された方法を推奨しているにもかかわらず、私はまだこの答えに賛成しています。マルチプロセスを通じて一貫性のあるデータが必要な場合は、ファイルシステムやデータベースに基づくContentProviderなどのSharedPreferences以外のものを使用する必要があります。

https://developer.android.com/reference/android/content/Context#MODE_MULTI_PROCESS


最終的な答え:

交換

getSharedPreferences(fileName, Context.MODE_PRIVATE);

getSharedPreferences(fileName, Context.MODE_MULTI_PROCESS);

ドキュメントによると:

Context.MODE_MULTI_PROCESS

SharedPreferencesロードフラグ:設定すると、共有プリファレンスインスタンスがこのプロセスですでにロードされている場合でも、ディスク上のファイルの変更がチェックされます。この動作は、アプリケーションに複数のプロセスがあり、すべてが同じSharedPreferencesファイルに書き込む場合に必要になることがあります。ただし、一般的に、プロセス間の通信にはより良い形式があります。

これは、Gingerbread(Android 2.3)以前のレガシー(ただし文書化されていない)動作であり、このようなリリースを対象とする場合、このフラグが暗示されます。Android 2.3(Gingerbread)以降のSDKバージョンを対象とするアプリケーションの場合、必要に応じてこのフラグを明示的に設定する必要があります。

これには単純な見落としがあることを私は知っていました。

于 2012-09-28T17:12:28.877 に答える
1

editor.commit();の代わりに呼び出してみてくださいeditor.apply();。通常は同じように動作するはずですが、時々奇妙な動作に気づきました。

于 2012-09-27T22:50:37.023 に答える
1

SharedPreferencesのドキュメントから、メソッド「apply()」はファイルに非同期(遅延)で書き込み、メソッド「commit()」は情報を同期(即時)にファイルに書き込みます。

また、ドキュメントから、上記のメソッドのいずれかを使用している間は、ステータスが変更される前に「apply()」書き込みが完了することを保証するため、アクティビティのライフサイクルについて注意する必要はないと言われています。同じシステムプロセス。

ただし、2つの異なるプロジェクトを使用しているため、それらは2つの異なるプロセスで実行され、プロジェクト1で「onResume()」が開始される前にプロジェクト2で「apply()」が終了するかどうかはわかりません。

同期書き込みを強制するには、「apply()」ではなく「commit()」を試してみることをお勧めします。これで問題が解決しない場合は、プロジェクト1の設定を読み取る前に数秒の遅延を追加して、問題がこの遅延書き込みに関連しているかどうかを確認できます。

-編集済み--

問題をデバッグするには、次のようにします。

1-Eclipseで、ビュー「ファイルエクスプローラー」を選択/追加し、ディレクトリに移動します。

/ data / data/[パッケージ名]/shared_prefs

パッケージ名は「com.myproject.shared」のようにする必要があります

2-保存した設定でファイルを選択し、「PCにダウンロード」ボタンを押します。

3-ファイルの内容が期待と一致するかどうかを確認します。

幸運を。

于 2012-09-27T23:56:18.597 に答える