以前一直没有用过 registerOnSharedPreferenceChangeListener 回调方法,今天用到了,就设置了下,结果发现不起作用,因为一直没有回调。

代码:

    mSp = this.getSharedPreferences(HuaweiPushReceiver.SP_Name, MODE_PRIVATE);
mSp.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
String token = sharedPreferences.getString(HuaweiPushReceiver.SP_KEY, null);
tv.setText("sp token:" + token);
Log.d(TAG, "sp token:" + token);
}
});

然后就搜索和看源码,已经有人提出了这个问题及解决办法,因为 SharedPreferences 的实现类 SharedPreferencesImpl 中对于观察者模式的储存使用的是 WeakHashMap ,所以当储存的 key 没有使用的时候就会回收掉,而上面的代码中使用的是匿名内部类,所以就容易被 GC 掉。

源码:

private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
new WeakHashMap<OnSharedPreferenceChangeListener, Object>(); SharedPreferencesImpl(File file, int mode) {
mFile = file;
mBackupFile = makeBackupFile(file);
mMode = mode;
mLoaded = false;
mMap = null;
startLoadFromDisk();
} ... public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(this) {
mListeners.put(listener, mContent);
}
}

解决办法:

不使用匿名内部类,同时在 onStart() 中注册,在 onStop() 中取消注册。

SharedPreferences mSp;

SharedPreferences.OnSharedPreferenceChangeListener mListener = new SharedPreferences
.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
String token = sharedPreferences.getString(HuaweiPushReceiver.SP_KEY, null);
tv.setText("sp token:" + token);
Log.d(TAG, "sp token:" + token);
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
... mSp = this.getSharedPreferences(HuaweiPushReceiver.SP_Name, MODE_PRIVATE);
}
...
} @Override
protected void onStart() {
super.onStart();
mClient.connect();
mSp.registerOnSharedPreferenceChangeListener(mListener);
} @Override
protected void onStop() {
mSp.unregisterOnSharedPreferenceChangeListener(mListener);
super.onStop();
}

SharePreference 注册 registerOnSharedPreferenceChangeListener 无法回调的问题的更多相关文章

  1. ZeroMQ接口函数之 :zmq_socket_monitor - 注册一个监控回调函数

    ZeroMQ 官方地址 :http://api.zeromq.org/4-2:zmq-socket-monitor zmq_socket_monitor(3) ØMQ Manual - ØMQ/4.1 ...

  2. (转)Unity3d通过Action注册事件,回调方法

    http://www.cnblogs.com/jisi5789/archive/2013/04/22/3036589.html using UnityEngine; namespace Liulala ...

  3. OpenGL的GLUT注册回调函数[转]

    OpenGL的注册回调函数 void glutDisplayFunc(void (*func)(void) ); 为当前窗口设置显示回调函数 void glutOverlayDisplayFunc(v ...

  4. cocos2d-x 2.2.0 如何在lua中注册回调函数给C++

    cocos2d-x内部使用tolua进行lua绑定,但是引擎并没有提供一个通用的接口让我们可以把一个lua函数注册给C++层面的回调事件.翻看引擎的lua绑定代码,我们可以仿照引擎中的方法来做.值得吐 ...

  5. android aidl通信 RemoteCallbackList客户端注册回调

    RemoteCallbackList 声明 public class RemoteCallbackList<E extends IInterface> 情况 在AIDL中客户端向服务端注册 ...

  6. 计算机基础,Python - 回调函数,使用装饰器注册回调函数

    1. 参考: https://en.wikipedia.org/wiki/Callback_(computer_programming) https://developer.mozilla.org/e ...

  7. 驱动开发:内核枚举Registry注册表回调

    在笔者上一篇文章<驱动开发:内核枚举LoadImage映像回调>中LyShark教大家实现了枚举系统回调中的LoadImage通知消息,本章将实现对Registry注册表通知消息的枚举,与 ...

  8. 驱动开发:内核监控Register注册表回调

    在笔者前一篇文章<驱动开发:内核枚举Registry注册表回调>中实现了对注册表的枚举,本章将实现对注册表的监控,不同于32位系统在64位系统中,微软为我们提供了两个针对注册表的专用内核监 ...

  9. Sipdroid实现SIP(一): 注册

    目录 注册: 预注册获取长号和用户注册 预注册返回长号 周期性用户注册 Receiver类概述 SipdroidEngine类概述 Sipdroid类中的用户注册: 注册代理和注册事务 注册代理类Re ...

随机推荐

  1. 包管理和环境管理软件Anaconda

    可以用于配置linux下得虚拟环境,该软件可以针对不同服务配置不同的运行环境,方便包管理与环境管理

  2. 〖Android〗dropbear一些操作命令备忘

    相关命令行: # 启动dropbear后台运行 /data/local/tmp/dropbear \ -A -N android -I -C -G -p \ -R /data/local/tmp/au ...

  3. 分享自己针对Automation做的两个成熟的框架(QTP 和Selenium)

    自己在google code中开源了自己一直以来做的两个自动化的框架,一个是针对QTP的一个是针对Selenium的,显而易见,一个是商业的UI automation工具,一个是开源的自动化工具. 只 ...

  4. Xamarin.Android服务的实现

    一.服务的生命周期 服务与活动一样,在它的整个生命周期中存在着一些事件,下图可以很好解释整个过程以及涉及到的方法: 在真实的使用中,Service来还包含一个OnBind方法,并且必须要使用该方法,但 ...

  5. excel 如何快速实现绝对引用

    当函数输入完成并框选数据区域后,变成如上效果时,按“F4键”即可

  6. Ubuntu18.04和OpenWrt 18.06.0 下使用aria2和BaiduExport处理百度盘下载

    Ubuntu下没有可用的百度盘客户端, 下载大文件如果通过浏览器就会特别不可靠. 可以使用Chrome插件 BaiduExport 得到下载链接和参数后, 通过aria2进行下载. Aria2安装 直 ...

  7. 用Redis的zset防御Session Flood

    zset (Sorted Set)是set的升级版本, 在set的基础上增加了一个顺序(或者权重)值属性, 属性在添加修改元素时候可以指定. 每次指定后zset会自动重新按新的值调整顺序. 可以理解为 ...

  8. Region使用全解

    代码地址如下:http://www.demodashi.com/demo/14799.html 前言 Region,即为区域,它表示的是canvas图层上的某一块封闭的区域.很多时候,我们会利用Reg ...

  9. 微信小程序解决方案合集

    微信小程序解决方案合集:http://www.wxapp-union.com/special/solution.html 跳坑系列:http://www.wxapp-union.com/forum.p ...

  10. Emacs中Golang的设置

    欲善其事,先利其器.下面记录一些使用Emacs24做golang开发中的一些有用设置,备忘用. 一,golang中的代码跳转 emacs24的go-mode中默认用godef-describe,god ...