SharedPreferences.onSharedPreferenceChangeListener 没有被一致调用 [英] SharedPreferences.onSharedPreferenceChangeListener not being called consistently

查看:33
本文介绍了SharedPreferences.onSharedPreferenceChangeListener 没有被一致调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm registering a preference change listener like this (in the onCreate() of my main activity):

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

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

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

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

The trouble is, the listener is not always called. It works for the first few times a preference is changed, and then it is no longer called until I uninstall and reinstall the app. No amount of restarting the application seems to fix it.

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

I found a mailing list thread reporting the same problem, but no one really answered him. What am I doing wrong?

推荐答案

这是一个偷偷摸摸的方案.SharedPreferences 将侦听器保存在 WeakHashMap 中.这意味着您不能使用匿名内部类作为侦听器,因为一旦离开当前作用域,它就会成为垃圾回收的目标.一开始它会工作,但最终会被垃圾收集,从 WeakHashMap 中删除并停止工作.

This is a sneaky one. SharedPreferences keeps listeners in a WeakHashMap. This means that you cannot use an anonymous inner class as a listener, as it will become the target of garbage collection as soon as you leave the current scope. It will work at first, but eventually, will get garbage collected, removed from the WeakHashMap and stop working.

在类的字段中保留对侦听器的引用,只要您的类实例没有被破坏,就可以了.

Keep a reference to the listener in a field of your class and you will be OK, provided your class instance is not destroyed.

即而不是:

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 中取消注册.

The reason unregistering in the onDestroy method fixes the problem is because to do that you had to save the listener in a field, therefore preventing the issue. It's the saving the listener in a field that fixes the problem, not the unregistering in onDestroy.

更新:Android 文档已更新警告 关于这种行为.因此,古怪的行为仍然存在.但现在已记录在案.

UPDATE: The Android docs have been updated with warnings about this behavior. So, oddball behavior remains. But now it's documented.

这篇关于SharedPreferences.onSharedPreferenceChangeListener 没有被一致调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆