Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android OnSharedPreferenceChangeListener未在MainActivity中启动?_Android_Sharedpreferences - Fatal编程技术网

Android OnSharedPreferenceChangeListener未在MainActivity中启动?

Android OnSharedPreferenceChangeListener未在MainActivity中启动?,android,sharedpreferences,Android,Sharedpreferences,假设用户可以从MainActivity的弹出对话框中更新共享首选项。在这种情况下,我必须收听onSharedPreferenceChanged事件,以便应用用户的新设置。当我在MyDialogFragment的onCreateDialog()方法中注册侦听器时,侦听器工作正常 public class MyDialogFragment extends dialogFragment { ... OnSharedPreferenceChangeListener listener = new

假设用户可以从MainActivity的弹出对话框中更新共享首选项。在这种情况下,我必须收听
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教程开始