2 woshiwoxingfu woshiwoxingfu 于 2012.10.25 11:14 提问

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 13: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 15: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);

}

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

Csdn user default icon
上传中...
上传图片
插入图片