SharedPreferences.onSharedPreferenceChangeListener が一貫して呼び出されない 質問する

SharedPreferences.onSharedPreferenceChangeListener が一貫して呼び出されない 質問する

私は次のように設定変更リスナーを登録しています (onCreate()メイン アクティビティの 内):

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

prefs.registerOnSharedPreferenceChangeListener(
   new SharedPreferences.OnSharedPreferenceChangeListener() {
       public void onSharedPreferenceChanged(
         SharedPreferences prefs, String key) {

         System.out.println(key);
       }
});

問題は、リスナーが常に呼び出されるわけではないことです。設定が変更された最初の数回は機能しますが、その後はアプリをアンインストールして再インストールするまで呼び出されなくなります。アプリケーションをいくら再起動しても、問題は解決しないようです。

メーリングリストを見つけました同じ問題を報告しましたが、誰も答えてくれませんでした。何が間違っているのでしょうか?

ベストアンサー1

これは巧妙なものです。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のドキュメントは更新しました警告この動作について。奇妙な動作は残っていますが、今では文書化されています。

おすすめ記事