Это подлый. 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 были обновлены с предупреждениями об этом поведении. Таким образом, странное поведение остается. Но теперь это задокументировано.