SharedPreferences 详解(多进程,存取数组解决方案)

一、SharedPreferences基本概念

文件保存路径:/data/data/<包名>/shared_prefs目录下目录下生成了一个SP.xml文件

SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。

实现SharedPreferences存储的步骤如下:

  1. 根据Context获取SharedPreferences对象
  2. 利用edit()方法获取Editor对象。
  3. 通过Editor对象存储key-value键值对数据。
  4. 通过apply()或者commit()方法提交数据。

二、SharedPreferences相关api

  • SharedPreferences.Editor api:完成数据写入操作
  • SharedPreferences api :完成数据读取操作

说明:所以的getXXX()方法,都支持默认值,即如果没有找到与当前key值对应的value,则返回我们自己设置的默认值。

  • commit()方法与apply()方法的比较

相同点:

  1. 二者都是提交preference修改数据
  2. 二者都是原子过程。

区别:

  1. apply没有返回值而commit返回boolean表明修改是否提交成功
  2. apply是将修改数据原子提交到内存,而后异步真正提交到硬件磁盘;而commit是同步的提交到硬件磁盘,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。
  3. apply方法不会提示任何失败的提示。

综合上述,由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。

  • 对api的理解

1. commit介绍:public abstract boolean commit ()

       修改你的preferences,从Editor到SharePreferences。它执行所请求的修改,替代SharedPreferences中的任何数据,当2个editor同时修改preferences ,最后一个commit成功。如果不关注返回值或在程序的main线程使用时,推荐使用apply(). 2. apply介绍:public abstract void apply ()         区别:commit将同步的将数据写到preferences;apply立即更改内存中的SharedPreferences,但是开始异步提交到磁盘中。保存失败你也不会得到任何提示信息,如果在这个sharedPreferences有另外一个editor执行一个定期的commit,此时一个apply依旧未完成。commit将被阻塞,直到所有异步操作完成,以及自己的commit。由于SharedPreferences在进程中是单实例的。在忽悠返回值的前提下,取代任何实例的commit或apply都是安全的。

来源: <http://tanqi0508.blog.163.com/blog/static/1883557772012111104326404/>

三、对数据集合的支持——可以直接写入一个 Set<String>类型的集合,但是默认只支持HashSet<String>类型,其他类型会被自动转型

Set<String>是一个接口,一般使用子类来完成相关的功能。

       如果你希望传入的Set是一个有序的(跟插入时的顺序一样),那么使用LinkedHashSet<String>类型,构造好一个LinkedHashSet<String>对象之后,调用 SharedPreferences.EditorputStringSet(String key, Set<String> values)写入。  按照常规的思维,通过SharedPreferences的getStringSet(String key)方法读取出来数据,然后强制转为LinkedHashLinked<String>,可是出现异常了,系统提示不能将HashSet<String>转为LinkedHashSet<String>类型。也就是说取出来的值已经不再是我们写入的类型了。所以就只能使用HashSet<String>默认的排序类型,这只能满足那些不关系顺序的情况。

四、SharedPreferences一次存入多个有序数据解决方案 (String 类型为例)——使用字符串拼接(StringBuilder)的方式

public void testSharedPreferences(Context context) {
        // 写数据操作
        final String regularExpression = "#";
        final String key = "key";
        final String[] strings = { "1111", "2222", "3333" };
        final String defaultValue = "5555";
        final String fileName = "filename";
        final StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < strings.length; i++) {
            stringBuilder.append(strings[i]);
            if (i != strings.length - 1) {
                stringBuilder.append(regularExpression);
            }
        }
        SharedPreferences preferencesWrite = context.getSharedPreferences(fileName, Context.MODE_WORLD_READABLE);
        SharedPreferences.Editor editor = preferencesWrite.edit();
        editor.putString(key, stringBuilder.toString());
        editor.apply();
  
       // 读数据操作
        SharedPreferences preferencesRead = context.getSharedPreferences(fileName, Context.MODE_WORLD_READABLE);
        final String resultStr = preferencesRead.getString(key, defaultValue); // 没有对应的key则返回“5555”
        final String[] resultArray = resultStr.split(regularExpression);  // 解析数据,字符串分割
        for (String str : resultArray) {
            System.out.println(str);
        }
}

五、SharedPreferences多进程支持(虽然支持,但是还是不靠谱的,大量同时读写操作也会存在问题)

public static int getMode() {
    // MODE_MULTI_PROCESS is always on in apps targeting Gingerbread
    // (Android 2.3) and below, and off by default in later versions
    return Build.VERSION.SDK_INT > 8 ? 4 : 0;
}
   
public void test() {
    SharedPreferences settings = context.getSharedPreferences("fileName", getMode());
}

下面是getSharedPreferences方法的定义和解释:

public abstract SharedPreferences getSharedPreferences (String name, int mode)

Added in API level 1

Retrieve and hold the contents of the preferences file 'name', returning a SharedPreferences through which you can retrieve and modify its values. Only one instance of the SharedPreferences object is returned to any callers for the same name, meaning they will see each other's edits as soon as they are made.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我的博客

安卓开发之SharedPreferences使用

Sharedpreferences保存数据类似配置信息格式的数据,使用简单类型的key-value对 主要方法有: Boolean contains(Strin...

2948
来自专栏技术小黑屋

系统剖析Android中的内存泄漏

作为Android开发人员,我们或多或少都听说过内存泄漏。那么何为内存泄漏,Android中的内存泄漏又是什么样子的呢,本文将简单概括的进行一些总结。

903
来自专栏java学习

Spring学习笔记3_Bean 获取与实例化

本章目录 Spring学习笔记3_Bean 获取与实例化 1.ApplicationContext与BeanFactory关系 2.Bean的实例化方式 ...

2998
来自专栏Flutter入门到实战

模仿安卓源码,手写过时的方法兼容低版本

我们经常会使用getColor(R.color.XXX)获取颜色的资源文件,但是在安卓6.0开始,这个方法被标注为过时,推荐使用两个参数的方法替代,如下图所示:

682
来自专栏我就是马云飞

Architecture Components ViewModel的控制。

前言 作为MVVM 系列的第二篇,我们来看一下之前提出的第二个问题,就是ViewModel是如果控制生命周期的,并且保证在一定范围内的唯一性。 ViewMode...

1599
来自专栏求索之路

Android源码设计模式解析与实战笔记

1.单一职责原则:比如说一个ImageLoader,需要加载图片的缓存图片,此时如果将这两个功能都放在一个类中,就违反了这个原则, 我们需要将不同的功能用类精...

4015
来自专栏刘望舒

Android内存优化(三)避免可控的内存泄漏

前言 内存泄漏向来都是内存优化的重点,它如同幽灵一般存于我们的应用当中,有时它不会现身,但一旦现身就会让你头疼不已。因此,如何避免、发现和解决内存泄漏就变得尤为...

18410
来自专栏C/C++基础

设计模式 (10)——适配器模式(Adapter Pattern,结构型)

使用设计模式可以提高代码的可复用性、可扩充性和可维护性。适配器模式(Adapter Pattern)属结构性模式,将一个类的接口转换成客户期望的另一个接口。适配...

622
来自专栏码匠的流水账

聊聊spring cloud gateway的ForwardedHeadersFilter

本文主要研究一下spring cloud gateway的ForwardedHeadersFilter

732
来自专栏何俊林

Android Multimedia框架总结(二十一)MediaCodec中创建到start过程(到jni部分)

最近我正在参加CSDN 2016年度博客之星评选,如果我的文章对你曾有过帮助,不妨点击文末【阅读原文】给我投上一票, 时间:11月28日到12月18日每天都可以...

2126

扫码关注云+社区