java preference xml,SharedPreferences & Preference XML 之间的羁绊(二)

羁绊和由来

默认值问题.

一般情况下, 如果使用自定义的 SharedPreferences, 并且也未保证 SharedPreferences.get[$Type](String,$Type) 第二个参数和 xml 中定义的默认值保持一致的话, 那么默认值就可能导致一些意想不到的问题.

例如,明明在调用 SharedPreferences时给了默认值, 但是偏偏在PreferenceActivity/Fragment(调用对应的xml)中显示是不同的. 反之亦然.

p.s. 肯定有人会说, 我怎么可能犯这样的错呢, 但是如果参数太多的话, 又因为疏忽, 难免还是会出这样的问题

解决办法

系统默认 SharedPreferences

若使用 PreferenceManager.getDefaultSharedPreferences(Context) 来获取 SharedPreferences 对象, 则在调用它之前, 先调用 PreferenceManager.setDefaultValues(Context, int, boolean).

自定义 SharedPreferences

若使用 Context.getSharedPreferences(String, int) 来获取 SharedPreferences对象,则在调用它之前,先调用 PreferenceManager.setDefaultValues (Context, String, int, int, boolean)

函数解释

PreferenceManager.setDefaultValues 会将 xml 中定义的所有 Preference 默认值设值到SharedPreferences 中. 因此, 不管 SharedPreferences.get 接口中设定的默认值是什么, 它都已经失去了默认值的作用, 除非在 xml 中没有定义默认值. 从而保证了默认值遵从 xml 设定的原则.

补遗

众所周知, SharedPreferences 是通过 Context.getSharedPreferences(String, int) 来获取实例的, 而在Android的App中至少存在1个Context, 即 Application Context, 然后就是 Activity Context, 而 Activity Context 所有函数最终是会调用 Application Context 所对应的函数的.

再来看 Application Context, 如果我没弄错的话, 那么 android.app.ContextImpl 就是它的实现, 其中有代码如下:

class ContextImpl extends Context {

private final static String TAG = "ContextImpl";

private final static boolean DEBUG = false;

private static final HashMap sSharedPrefs =

new HashMap();

...

@Override

public SharedPreferences getSharedPreferences(String name, int mode) {

SharedPreferencesImpl sp;

synchronized (sSharedPrefs) {

sp = sSharedPrefs.get(name);

if (sp == null) {

File prefsFile = getSharedPrefsFile(name);

sp = new SharedPreferencesImpl(prefsFile, mode);

sSharedPrefs.put(name, sp);

return sp;

}

}

if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||

getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {

// If somebody else (some other process) changed the prefs

// file behind our back, we reload it. This has been the

// historical (if undocumented) behavior.

sp.startReloadIfChangedUnexpectedly();

}

return sp;

}

}

从这段代码看来, SharedPreferences 可以说就是单例. 因此, 在多个 Activity 之间操作的情况下(例如, 调用 Activity.startActivityForResult(Intent, int) 启动一个Dialog样式的 Activity ), 是无需考虑 SharedPreferences 对象传递的问题的.

需要注意的是, 虽然在 SharedPreferences 的实现 android.app.SharedPreferencesImpl 中, 是用 WeakHashMap 来保存所有 listener 的, 但还是建议 registerOnSharedPreferenceChangeListener  & unregisterOnSharedPreferenceChangeListener) 成对调用, 以免造成不必要的麻烦.

参考资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值