[解決済み】SharedPreferences.onSharedPreferenceChangeListenerが一貫して呼び出されない。
2022-04-18 13:41:40
質問
私はこのようにプリファレンス変更リスナーを登録しています。
onCreate()
を使用します)。
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(
SharedPreferences prefs, String key) {
System.out.println(key);
}
});
問題は、リスナーが常に呼び出されるわけではないことです。プリファレンスを変更した最初の数回は動作しますが、その後、アプリをアンインストールして再インストールするまで呼び出されなくなります。アプリケーションをいくら再起動しても直らないようです。
メーリングリストを発見 スレッド 同じ問題を報告しているのですが、誰も彼に本当に答えていません。私は何を間違えているのでしょうか?
解決方法は?
これはずるいですね。SharedPreferences はリスナーを WeakHashMap に保持します。つまり、リスナーとして無名の内部クラスを使うことはできません。現在のスコープを離れるとすぐにガベージコレクションのターゲットになってしまうからです。最初は動作しますが、最終的にはガベージコレクションの対象となり、WeakHashMap から削除され、動作しなくなります。
リスナーへの参照をクラスのフィールドに保持しておけば、クラスのインスタンスが破壊されない限りは問題ありません。
すなわち、代わりに
prefs.registerOnSharedPreferenceChangeListener(
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// Implementation
}
});
はこれを行う。
// Use instance field for listener
// It will not be gc'd as long as this instance is kept referenced
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// Implementation
}
};
prefs.registerOnSharedPreferenceChangeListener(listener);
onDestroyメソッドで登録を解除すると問題が解決するのは、そのためにリスナーをフィールドに保存する必要があり、その結果問題が発生しないためです。問題を解決するのは、リスナーをフィールドに保存することであり、onDestroyで登録を解除することではありません。
アップデイト : Androidのドキュメントは 更新 で 警告 この動作について ですから、奇妙な動作は残っています。しかし、今は文書化されています。
関連
-
[解決済み】Looper.prepare()を呼び出していないスレッド内でハンドラを作成できない。)
-
[解決済み】Android TextView : "setTextで表示されたテキストを連結しない" について
-
[解決済み】「ArrayAdapterはリソースIDがTextViewであることが必要」XMLの問題点
-
[解決済み】OnFragmentInteractionListenerを実装する方法
-
[解決済み] 現在のテーマでスタイル 'coordinatorLayoutStyle' を見つけることができませんでした。
-
[解決済み】Android 8:クリアテキストのHTTPトラフィックが許可されない
-
[解決済み] Looper.prepare()を呼び出していないスレッドではハンドラを作成できない
-
[解決済み] SDKの場所がandroid studioで見つからない
-
[解決済み] FragmentでonActivityResultが呼び出されない
-
[解決済み】Android Mのパーミッション:onRequestPermissionsResult()が呼び出されない件
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】パッケージ名(Google Analytics)に一致するクライアントが見つからない - 複数のproductFlavorsとbuildTypes
-
[解決済み】react-native: コマンドが見つかりません。
-
[解決済み】OnFragmentInteractionListenerを実装する方法
-
[解決済み】Android Intent コンストラクタを解決できない
-
[解決済み】Android Studioです。「プロジェクトが C ドライブに作成されている場合、「タスク ':app:mergeDebugResources' の実行に失敗しました。
-
[解決済み】"ビットマップが大きすぎてテクスチャにアップロードできない"
-
[解決済み】リストビューにonclicklistenerを追加する(android)
-
[解決済み】Android Studioで最新バージョンのgradleを使用する方法
-
[解決済み] TypeError: cb.apply は関数ではありません。
-
[解決済み] 起動アクティビティを特定できませんでした。デフォルトのアクティビティが見つかりませんでした