小编典典

SharedPreferences.onSharedPreferenceChangeListener 没有被一致地调用

all

我正在注册一个这样的偏好更改侦听器(在onCreate()我的主要活动中):

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

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

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

问题是,侦听器并不总是被调用。它适用于首选项更改的前几次,然后在我卸载并重新安装应用程序之前不再调用它。重新启动应用程序似乎无法修复它。

我发现一个邮件列表线程报告了同样的问题,但没有人真正回答他。我究竟做错了什么?


阅读 116

收藏
2022-04-29

共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
文档已更新,包含有关此行​​为的警告。所以,古怪的行为仍然存在。但现在它已记录在案。

2022-04-29