1

現在、SharedPreferences を使用して、AlarmManager を通じて開始された BroadcastReceiver で作業を実行する項目のリストを追跡しています。特定のシナリオを除いて、すべてがうまく機能します。作業を実行する新しいアイテムをトリガーすると、その作業を実行させてから、そのアイテムを削除します (すべて SharedPreferences 編集を介して)。アプリケーションの実行中に、それは美しく機能します。リストに何もなく、タスク マネージャーを開いてアプリケーションを強制終了すると、突然項目が BroadcastReceiver (アプリケーションの終了後も実行中) に表示されます。この動作の原因は何ですか? アプリケーションの終了時にすべてのレシーバーを強制終了する必要がありますか? レシーバーがまだ実行されている場合、Activity の終了はデフォルトで別の SharedPreferences オブジェクトに戻りますか?

SharedPreferences オブジェクトからアイテムを追加/削除するコード

final SharedPreferences prefs = context.getSharedPreferences(Config.PREFS_NAME,
                Context.MODE_PRIVATE);
final Editor editor = prefs.edit();
mUpdates = prefs.getStringSet(Config.PREFS_KEY_ACTIVE_TASKS, new HashSet<String>());

if (!mUpdates.contains(key)) {
    mUpdates.add(key);
} else {
    mUpdates.remove(key);
}
editor.putStringSet(Config.PREFS_KEY_ACTIVE_TASKS, mUpdates);
editor.apply();

放送受信機コード

public void onReceive(Context context, Intent intent) {
    SharedPreferences prefs = context.getSharedPreferences(Config.PREFS_NAME, Context.MODE_PRIVATE);
    if(prefs.contains(Config.PREFS_KEY_ACTIVE_TASKS)) {
        Set<String> updates = prefs.getStringSet(Config.PREFS_KEY_ACTIVE_TASKS, null);
        if(updates != null) {
            Log.d("RECEIVER","Size="+updates.size());
            for(String key : updates) {
                EntityChangeManager.notifyListeners(key);
            }
        }
    }
}

コードを実行して初期リストからオブジェクトを追加/削除すると、予想どおり

04-30 20:04:44.165: D/RECEIVER(27079): Size=1
04-30 20:04:44.165: D/RECEIVER(27079): Size=0

アプリケーションを強制終了すると、

04-30 20:04:43.244: D/ActivityThread(27079): setTargetHeapUtilization:0.25
04-30 20:04:43.244: D/ActivityThread(27079): setTargetHeapIdealFree:8388608
04-30 20:04:43.254: D/ActivityThread(27079): setTargetHeapConcurrentStart:2097152
04-30 20:04:43.264: D/RECEIVER(27079): Size=1

興味がある点:

  • 受信機は毎秒実行されます
  • レシーバーは AlarmManager から開始されます
  • 宣言に特別な設定はありません
  • これは、アプリケーションをアンインストールした後に繰り返し可能であり、レシーバーのすべての設定をクリアします (別の設定を使用していた場合)。
4

3 に答える 3

2

に変更editor.apply();editor.commit()ます。アプリを強制終了すると、変更がディスクに書き込まれない場合があります。http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply()の公式ドキュメントから

設定を永続ストレージに同期的に書き込む commit() とは異なり、apply() は変更をメモリ内の SharedPreferences にすぐにコミットしますが、ディスクへの非同期コミットを開始するため、失敗は通知されません。この SharedPreferences の別のエディターが通常の commit() を実行し、apply() がまだ未解決である場合、commit() はすべての非同期コミットとコミット自体が完了するまでブロックされます。

于 2013-05-01T03:57:19.773 に答える
1

StringSet を使用してニュアンスに遭遇した場合の解決策は、StringSet 自体と連携して、SharedPreferences オブジェクト (StringSet.size() など) に別の属性を書き込むことです。その理由は、SharedPreferences ライブラリはオブジェクトを格納されたオブジェクトと比較するだけであり、データの追加/削除によってオブジェクト自体が変更されるとは限らないため、違いがないように見えます。

オブジェクトのサイズを確認できます。編集時にサイズが 0 の場合は、編集する代わりに、オブジェクトを null に設定してから SharedPreferences に保存します。私は 2 番目の sharedpref 設定を選択しましたが、それ以降は正常に機能しています。

于 2013-05-01T12:35:14.717 に答える