不一致地调用SharedPreferences.onSharedPreference

不一致地调用SharedPreferences.onSharedPreferenceChangeListener

我正在注册一个像这样的首选项更改监听器(在onCreate()我的主要活动):

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);prefs.registerOnSharedPreferenceChangeListener(
   new SharedPreferences.OnSharedPreferenceChangeListener() {
       public void onSharedPreferenceChanged(
         SharedPreferences prefs, String key) {

         System.out.println(key);
       }});

问题是,听者并不总是被调用。它工作在最初的几次首选项被改变,然后它不再被调用,直到我卸载和重新安装应用程序。再多的重新启动应用程序似乎都无法修复它。

我找到了一份邮件列表螺纹报告同样的问题,但没有人真正回答他。我做错什么了?


青春有我
浏览 538回答 3
3回答

白猪掌柜的

这是个鬼鬼祟祟的。SharedPreferences将侦听器保存在WeakHashMap中。这意味着您不能使用匿名内部类作为侦听器,因为一旦离开当前作用域,它将成为垃圾回收的目标。它一开始可以工作,但最终会被垃圾收集、从WeakHashMap中删除并停止工作。在类的字段中保持对侦听器的引用,只要类实例未被销毁,您就会没事。即:而不是:prefs.registerOnSharedPreferenceChangeListener(   new SharedPreferences.OnSharedPreferenceChangeListener() {   public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {     // Implementation   }});这样做:// Use instance field for listener // It will not be gc'd as long as this instance is kept referencedlistener = new SharedPreferences.OnSharedPreferenceChangeListener() {   public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {     // Implementation   }};prefs.registerOnSharedPreferenceChangeListener(listener);在onDesty方法中注销的原因是修复了这个问题,因为要做到这一点,就必须在字段中保存侦听器,从而防止问题的发生。解决问题的是在字段中保存侦听器,而不是在onDesty中取消注册。更新:Android的文档更新带着警告关于这种行为。所以,古怪的行为依然存在。但现在它被记录在案了。

守着星空守着你

因为这是这个主题最详细的页面,所以我想添加我的50 ct。我遇到的问题是OnSharedPreferenceChangeListener没有被调用。我的SharedPreferences是在主活动开始时通过以下方式检索的:prefs = PreferenceManager.getDefaultSharedPreferences(this);我的PreferenceActivity代码很短,除了显示首选项之外,什么也不做:public class Preferences extends PreferenceActivity {     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         // load the XML preferences file         addPreferencesFromResource(R.xml.preferences);     }}每次按下菜单按钮,我就从主活动创建PreferenceActivity:@Overridepublic boolean onPrepareOptionsMenu(Menu menu) {     super.onCreateOptionsMenu(menu);     //start Preference activity to show preferences on screen     startActivity(new Intent(this, Preferences.class));     //hook into sharedPreferences. THIS NEEDS TO BE DONE AFTER CREATING THE ACTIVITY!!!     prefs.registerOnSharedPreferenceChangeListener(this);     return false;}注在本例中,注册OnSharedPreferenceChangeListener需要在创建PreferenceActivity之后完成,否则将不会调用主活动中的Handler!我花了些时间才意识到.。

慕后森

这个被接受的答案是可以接受的,对我来说,它正在创造新实例每次活动恢复时那么,在活动中保持对侦听器的引用如何?OnSharedPreferenceChangeListener myPrefListner = new OnSharedPreferenceChangeListener(){       public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {          // your stuff       }};在你的时空里@Override     protected void onResume() {     super.onResume();               getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(myPrefListner);     }     @Override     protected void onPause() {              super.onPause();               getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(myPrefListner);}这将非常类似于你正在做的事情,除非我们保持一个硬引用。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Android