SharedPreference注册OnSharedPreferenceChangeListener问题
采用如下代码注册是肯定要失败的:
SharedPreferences sp = getSharedPreferences("AndroidDemo", Context.MODE_PRIVATE);
sp.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) {
}
});
源码解释如下:
/**
* Registers a callback to be invoked when a change happens to a preference.
*
* <p class="caution"><strong>Caution:</strong> The preference manager does
* not currently store a strong reference to the listener. You must store a
* strong reference to the listener, or it will be susceptible to garbage
* collection. We recommend you keep a reference to the listener in the
* instance data of an object that will exist as long as you need the
* listener.</p>
*
* @param listener The callback that will run.
* @see #unregisterOnSharedPreferenceChangeListener
*/
void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
实现为SharedPreferencesImpl.java 中的
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(this) {
mListeners.put(listener, mContent);
}
}
mListeners定义在:
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
可以看出是个弱引用的Hashmap. 无法回调主要是因为注册的监听器使用了匿名内部类,由于SharedPreferences保持在WeakHashMap中,这意味着你不能监听一个匿名内部类,因为它会成为垃圾收集的目标,只要你离开目前的范围,它将会被垃圾收集,从WeakHashMap中删除并停止工作。
应该使用当前类作为监听器,即在当前类中实现SharedPreferences.OnSharedPreferenceChangeListener接口,只要当前类的实例没有被回收,就可以保证回调的有效性。
所以注册此监听时,最好不要使用匿名内部类,否则会由于垃圾回收机制导致此监听无效,而无法回调。
本文解析了SharedPreferences中的OnSharedPreferenceChangeListener监听器的工作原理,强调了使用匿名内部类注册监听器时存在的问题,并给出了正确的使用方式。
1048

被折叠的 条评论
为什么被折叠?



