android中SharePreference的使用

前段时间项目中用到了进程间的通信,用到了之前的SharePreference结果会导致获取脏数据的问题,因此觉得有必要写下SharePreference的使用。

前言

因为SharedPreferences在SDK2.3 之前是默认的,确实可以通过设置MODE_MULTI_PROCESS实现多进程访问,SDK2.3之后就需要手动设置,但是这个标志在 SDK6.0 的时候已经被Deprecated,Android为什么要把这么一个简单易用的进程间通讯方式废弃掉呢,看下源码就可以知道,原因就是它并不能保证数据的安全性和准确性,并没有实现并发修改的机制,所以官方也就不推荐了.

SharedPreferenced支持三个不同的mode

之前默认的一般用的都是MODE_PRIVATE, 也是现在唯一的mode,因为另外两个mode已经被废弃掉了,mode指定的是其他应用是否可以访问或者修改指定的SharedPreferences, 从字面上就能看的出来,MODE_PRIVATE表示其他应用不可读,不可写,MODE_WORLD_READABLE表示其他应用可读但不可写,MODE_WORLD_WRITEABLE表示其他应用可读可写,但是现在后两个mode已经被废弃掉了,官方给的提示是:全局可见的文件是很为危险的方式,容易导致安全漏洞,推荐更普遍的通信方式,比如:ContentProvider, BroadcastReceiver或者Service, 而且因为这个权限设置是在生成SharedPreferences文件的时候就设置的,但是不能保证这个权限设置在备份或者恢复的时候保留。总而言之,一句话,还是用MODE_PRIVATE吧,应用间通信不要考虑。

apply or commit?

这里写图片描述

官方给的文档解释是:

这两个方法的区别在于:
1. apply没有返回值而commit返回boolean表明修改是否提交成功
2. apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。
3. apply方法不会提示任何失败的提示。
由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。

SharePreference 的使用上尽量用 apply 替换掉 commit 吧,不用担心异步带来的读取时序的问题,看官方原文说明如下:

这里写图片描述


OnSharedPreferenceChangeListener无法回调问题?

SharedPreferences sp = getSharedPreferences("default", Context.MODE_PRIVATE);
sp.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
    @Override
    public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) {
    }
});

这种写法看上去没有什么问题,而且很多时候开始几次onSharedPreferenceChanged方法也可以被调用。但是过一段时间你会发现前面的方法突然不再被触发。

原因剖析,看下SharedPreferencesImpl中的源码就彻底明白了。

这里写图片描述

这里写图片描述

无法回调主要是因为注册的监听器使用了匿名内部类,由于SharedPreferences保持在WeakHashMap中,这意味着你不能监听一个匿名内部类,因为它会成为垃圾收集的目标,只要你离开目前的范围,它将会被垃圾收集,从WeakHashMap中删除并停止工作。

应该使用当前类作为监听器,即在当前类中实现SharedPreferences.OnSharedPreferenceChangeListener接口,只要当前类的实例没有被回收,就可以保证回调的有效性。

所以注册此监听时,最好不要使用匿名内部类,否则会由于垃圾回收机制导致此监听无效,而无法回调。

public class MyActivity extends Activity implements OnSharedPreferenceChangeListener {
      @Override
      public void onCreate(Bundle SavedInstanceState) {
         Context context = getApplicationContext();
         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
         prefs.registerOnSharedPreferenceChangeListener(this); // 注册
      }

      public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
         // 事件处理器. 根据数据的变化,对显示和行为作改变
      }
}

@Override
    protected void onDestroy() {
        super.onDestroy();
        prefs.unregisterOnSharedPreferenceChangeListener(this);
    }

参考

请不要滥用SharePreference

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值