woshiwoxingfu
woshiwoxingfu
2012-10-25 03:14
采纳率: 100%
浏览 5.9k

SharedPreferences.onSharedPreferenceChangeListener不能一直被调用

我注册一个优先权来改变监听器想这样(在我的主activity的onCreate()中):

SharedPreferences prefs = 
    PreferenceManager.getDefaultSharedPreferences(this);

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

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

问题就是,监听器并不能一直被调用。它只在最开始的几次起作用,能够让优先权改变,然后就直到我卸载然后重新安装引用程序他都不再被调用。重启了应用程序很多次好像都不能修复。
怎么才能解决呢?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • Sueyexin
    Sueyexin 2012-10-25 05:46
    已采纳

    这是一个很诡异的问题。SharedPreferences一直在WeakHashMap保持监听。这意味着你不能用匿名的内部类作为监听器,因为一旦你离开当前的范围它将变成回收的目标。它将首先工作,但是最终,仍然要被回收,被从WeakHashMap移除然后停止工作。
    在你的类中的一个位置引用一个监听器,这样就好了,提供你的类的实例也不会被销毁。
    也就是代替:

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

    这样做:

    listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
      public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
      }
    };
    prefs.registerOnSharedPreferenceChangeListener(listener);
    

    在onDestroy方法取消注册修复了这个问题,原因是因为这样做你不得不在一个field保存一个监听器,因此防止了这个问题的产生。这是在一个field保存这个监听器来修复这个问题的方法,不是在onDestroy取消注册。

    点赞 评论
  • niangzhi
    niangzhi 2012-10-25 07:34

    对我来说就是每次创建新的实例,恢复activity
    所以在activity中保持监听器的参数怎么样

    OnSharedPreferenceChangeListener myPrefListner = new OnSharedPreferenceChangeListener(){
          public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
          }
    }
    

    在你的onResume和onPause

    @Override     
    protected void onResume() {
        super.onResume();          
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(myPrefListner);     
    }
    
    @Override     
    protected void onPause() {         
        super.onPause();          
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(myPrefListner);
    
    }
    

    除了我们维护一个参数以为,这都和你想要的非常类似。

    点赞 评论

相关推荐