Android OnSharedPreferenceChangeListener未在MainActivity中启动?
假设用户可以从MainActivity的弹出对话框中更新共享首选项。在这种情况下,我必须收听Android OnSharedPreferenceChangeListener未在MainActivity中启动?,android,sharedpreferences,Android,Sharedpreferences,假设用户可以从MainActivity的弹出对话框中更新共享首选项。在这种情况下,我必须收听onSharedPreferenceChanged事件,以便应用用户的新设置。当我在MyDialogFragment的onCreateDialog()方法中注册侦听器时,侦听器工作正常 public class MyDialogFragment extends dialogFragment { ... OnSharedPreferenceChangeListener listener = new
onSharedPreferenceChanged
事件,以便应用用户的新设置。当我在MyDialogFragment
的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);
}
但是,如果我从MainActivity
的onResume()
以相同的方式注册同一个侦听器,则当SharedReference发生更改时,侦听器将不工作
主要活动
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);
}
唯一的区别是,在MainActivity的方法中声明SharedReferences
时,我将getActivity()
替换为this
。这是否意味着上述侦听器无法在MainActivity的范围内工作?来自:
您不能使用匿名内部类作为侦听器,因为一旦您离开当前作用域,它将成为垃圾收集的目标。它一开始会工作,但最终会收集垃圾,从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");
}
};
在
MyDialogFragment
中,侦听器在类作用域中定义-将与类寿命一样长。在您的onResume()
中,侦听器被定义为onResume()中的局部变量,因此当onResume()
返回时,侦听器超出范围,并且由于其中解释的原因而被垃圾收集。注意,在这个答案中,我们有listener=newsharedpreferences.OnSharedPreferenceChangeListener(){//etc
当您在共享首选项ChangeListener=new//etc上执行操作时,您定义了一个局部变量。谢谢!您能为我详细说明一下吗?我想我知道垃圾收集问题。您的回答与我的方法有什么不同?(我代码中的哪部分包括匿名内部类?)如果您查看我的代码,它与您提供的链接中作为答案发布的代码完全相同。这是否意味着垃圾收集不是我的问题?请仔细查看;)感谢您的回答。我仍然不完全理解listener=new SharedReferences.OnSharedPreferenceChangeListener(){}之间的区别onSharedPreferenceChangeListener=new something..它们本质上是一样的吗?哦。区别在于listener
应该在前面定义(在类范围内),而我在onResume()中定义它
,使其成为局部变量。是否正确?@MaximusS:correct-listener=new…`是一个与类(片段)一样长的类字段,而onSharedPreferenceChangeListener=…
是onResume()中的局部变量
。其中一个将继续存在并侦听—另一个在onResume结束生命时也将停止—并且很快被Java收集而不侦听anymore@MaximusS:我在你发表第二篇评论时发表了我的评论-你的第二篇评论是正确的-你需要阅读一些Java-从Oracle教程开始