假设用户可以从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的范围内工作吗?
答案 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");
}
};