OnSharedPreferenceChangeListener未在MainActivity中触发?

时间:2014-02-04 02:00:44

标签: android sharedpreferences

假设用户可以从MainActivity的弹出对话框更新共享首选项。在这种情况下,我必须收听onSharedPreferenceChanged事件才能应用用户的新设置。当我在MyDialogFragment的{​​{1}}方法中注册监听器时,监听器正常工作。

onCreateDialog()

但是,如果我从public class MyDialogFragment extends dialogFragment { ... OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sf, String key) { Log.e("change", "pref changed"); } }; SharedPreferences sp = getActivity().getsharedPreferences(myKey, Context.MODE_PRIVATE); sp.registerOnSharedPreferenceChangeListener(listener); } 的{​​{1}}以相同的方式注册同一个侦听器,则在更改共享首选项时,侦听器不起作用。

MainActivity

MainActivity

唯一的区别是,在MainActivity的方法中声明onResume()时,我将protected void onResume() { super.onResume(); OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sf, String key) { Log.e("change", "pref changed"); } }; SharedPreferences sp = this.getsharedPreferences(myKey, Context.MODE_PRIVATE); sp.registerOnSharedPreferenceChangeListener(listener); } 替换为getActivity()。预计上述监听器无法在MainActivity的范围内工作吗?

2 个答案:

答案 0 :(得分:0)

MyDialogFragment中,监听器在类范围内定义 - 将与类一样长。在onResume()中,侦听器被定义为作为onResume()中的局部变量,因此当onResume()返回时,侦听器超出范围,并且由于SharedPreferences.onSharedPreferenceChangeListener not being called consistently中解释的原因它是垃圾收集。请注意,在此答案中,listener = new SharedPreferences.OnSharedPreferenceChangeListener() { //etc执行时OnSharedPreferenceChangeListener listener = new // etc,因此您定义了一个局部变量。

答案 1 :(得分:-1)

来自SharedPreferences.onSharedPreferenceChangeListener not being called consistently

  

您不能将匿名内部类用作侦听器,因为一旦离开当前作用域,它将成为垃圾收集的目标。它最初会起作用,但最终会收集垃圾,从WeakHashMap中删除并停止工作。

在类的字段中保留对侦听器的引用,如果您的类实例未被销毁,您就可以了。

// 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);

更新: 下面的代码片段是完全在函数内声明的对象。在你的情况下,它在OnCreateDialog或OnResume中声明。因此,当函数超出范围时,它会收集垃圾。您需要在类级别字段中声明此对象,然后在OnResume或OnCreateDialog中注册侦听器。

OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sf, String key) {
      Log.e("change", "pref changed");
    }
  };