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 条评论
登录 后参与评论

相关文章

来自专栏AILearning

Apache Spark 2.2.0 中文文档 - Spark 编程指南 | ApacheCN

Spark 编程指南 概述 Spark 依赖 初始化 Spark 使用 Shell 弹性分布式数据集 (RDDs) 并行集合 外部 Data...

2346
来自专栏用户2442861的专栏

Nginx源码剖析之内存池,与内存管理

    Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like...

1084
来自专栏浪淘沙

Spark Core 学习笔记

1:Spark Core:内核,也是Spark中最重要的部分,相当于Mapreduce                 SparkCore 和 Mapredu...

1312
来自专栏FD的专栏

一步步理解python的异步IO

看到越来越多的大佬都在使用python的异步IO,协程等概念来实现高效的IO处理过程,可是我对这些概念还不太懂,就学习了一下。 因为是初学者,在理解上有很多不到...

1042
来自专栏海纳周报

synchronized关键字的语义

上一篇文章,我们讲到,如果发生了多个线程共同访问一个全局变量的时候,就会发生各种意料之外的情况。其实现实生活中有很多这样的例子。我举一个例子。 一群人都要过河,...

3437
来自专栏武培轩的专栏

搜狗面经汇总

volatile是变量修饰符,其修饰的变量具有可见性,Java的做法是将该变量的操作放在寄存器或者CPU缓存上进行,之后才会同步到主存,使用volatile修饰...

1185
来自专栏码神联盟

面试题 | 《Java面试题集》-- 第三套

varchar2分别在oracle的sql和pl/sql中都有使用,oracle 在sql参考手册和pl/sql参考手册中指出:oracle sql varch...

1022
来自专栏大内老A

WCF技术剖析之十七:消息(Message)详解(上篇)

消息交换是WCF进行通信的唯一手段,通过方法调用(Method Call)形式体现的服务访问需要转化成具体的消息,并通过相应的编码(Encoding)才能通过传...

3459
来自专栏网络

如何封装属于自己的ajax

如何封装属于自己的ajax?小编带你探探路。。 // 1准备一个电话 准备ajax // 2 拨号 建立 建立连接 (跟服务器) // 3 发送 ...

1937
来自专栏大内老A

WCF后续之旅(16): 消息是如何分发到Endpoint的--消息筛选(Message Filter)

在介绍终结点的ListenUriMode时,我们提到了两个特殊的对象ChannelDispatcher和ChannelListener。这两个对象在整个WCF的...

1857

扫码关注云+社区