欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android数据存储之SharedPreferences详细总结

程序员文章站 2024-03-17 20:38:52
...

Android中常见的几种存储方式:

  1. SharedPreferences
  2. SQLite数据库存储
  3. 文件存储
  4. 网络存储

其中也许最常用的就是SharedPreferences存储和文件存储了,今天总结一下SharedPreferences。带着问题学习SharedPreferences:
问题:

  • 存储的位置是在哪
  • SharedPreferences存储的文件格式是什么
  • 如何查看
  • 创建的时候需要context,不同的context创建有没有区别
  • 创建的几种mode以及区别
  • apply和commit的区别
  • 存取数据使用多张表还是一张表

看完下面的讲解,你应该就能回答上面的问题了

google官方说明

SharedPreferences 类提供了一个通用框架,以便您能够保存和检索原始数据类型的永久性键值对。 您可以使用 SharedPreferences 来保存任何原始数据:布尔值、浮点值、整型值、长整型和字符串。 此数据将跨多个用户会话永久保留(即使您的应用已终止亦如此)。

要获取应用的 SharedPreferences 对象,请使用以下两个方法之一:

  • getSharedPreferences() - 如果您需要多个按名称(使用第一个参数指定)识别的首选项文件,请使用此方法。
  • getPreferences() - 如果您只需要一个用于 Activity 的首选项文件,请使用此方法。 由于这将是用于 Activity 的唯一首选项文件,因此无需提供名称。

我先在Activity A中写入

SharedPreferences settings = getSharedPreferences("test", 0);
SharedPreferences.Editor editor = settings.edit();
editor.putInt("num", 23);
System.out.println("-----------写入");

打印:
I/System.out: ———–写入

然后在Activity B中查看

SharedPreferences settings = getSharedPreferences("test", 0);
int num = settings.getInt("num", 0);
System.out.println("-----------num="+num);

打印:
I/System.out: ———–num=23

存储的位置是在哪

如果你使用的是3.0以前的Android studio版本,可以在通过DDMS的【File Explorer】中查看,如果你使用的是3.0以及以后的Android studio版本,可以直接通过一下步骤打开

点击 View > Tool Windows > Device File Explorer 或工具窗口栏中的 Device File Explorer 按钮以打开设备文件浏览器。

注意需要用模拟器查看,手机没有root是看不到的

Android数据存储之SharedPreferences详细总结

找到data\data\程序包名\shared_prefs目录,你会发现你刚创建的文件
Android数据存储之SharedPreferences详细总结

SharedPreferences存储的文件格式是什么

Android数据存储之SharedPreferences详细总结
我想你应该也看到了是xml文件
内容是:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <int name="num" value="23" />
</map>

如何查看

如果是开发上面就是查看过程,如果是真机需要把手机root,才有权限查看

创建的时候需要context,不同的context创建有没有区别

我是在不同的Activity中写入和查看的,但是操作的是同一个test.xml,所以不同的Context操作只要getSharedPreferences(“test”, 0);获取SharedPreferences时传入的第一个参数name相同就得到是相同的SharedPreferences,操作的是同一个xml文件。

那么如何获取一个Activity单独的SharedPreferences呢?Google已经说了

getPreferences() - 如果您只需要一个用于 Activity 的首选项文件,请使用此方法。 由于这将是用于 Activity 的唯一首选项文件,因此无需提供名称

可以查看源码,其实就是获取了当前Activity的ClassName,所以这个name是单独的,所以产生的也是用于 此Activity 的唯一首选项文件

/**
     * Retrieve a {@link SharedPreferences} object for accessing preferences
     * that are private to this activity.  This simply calls the underlying
     * {@link #getSharedPreferences(String, int)} method by passing in this activity's
     * class name as the preferences name.
     *
     * @param mode Operating mode.  Use {@link #MODE_PRIVATE} for the default
     *             operation.
     *
     * @return Returns the single SharedPreferences instance that can be used
     *         to retrieve and modify the preference values.
     */
    public SharedPreferences getPreferences(@Context.PreferencesMode int mode) {
        return getSharedPreferences(getLocalClassName(), mode);
    }

创建时的几种mode以及区别

上面获取SharedPreferences的时候我直接使用的是getSharedPreferences(“test”, 0),第二个参数传入的是0,代表操作模式是MODE_PRIVATE
操作模式有以下几种:

  1. MODE_PRIVATE
  2. MODE_WORLD_READABLE
  3. MODE_WORLD_WRITEABLE
  4. MODE_APPEND
  5. MODE_MULTI_PROCESS

Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容, 而不是擦除以前的,否则就创建新文件。
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取。
MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。

以上是我看的网上的说法,但是我在最新的Android Studio上开发,也就是在Android Studio3.1上去看到了下面的场景:
Android数据存储之SharedPreferences详细总结

MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE和MODE_MULTI_PROCESS都被废弃了

然后我又试了下MODE_APPEND,又给了我以下的提示:
Must be one or more of: Context.MODE_PRIVATE, Context.MODE_WORLD_READABLE, Context.MODE_WORLD_WRITEABLE, Context.MODE_MULTI_PROCESS less… (⌘F1)

看来目前能用的只能是MODE_PRIVATE了,其他的不用考虑了

apply和commit的区别

先看看两者的说明:

/**
* Commit your preferences changes back from this Editor to the
* {@link SharedPreferences} object it is editing.  This atomically
* performs the requested modifications, replacing whatever is currently
* in the SharedPreferences.
*
* <p>Note that when two editors are modifying preferences at the same
* time, the last one to call commit wins.
*
* <p>If you don't care about the return value and you're
* using this from your application's main thread, consider
* using {@link #apply} instead.
*
* @return Returns true if the new values were successfully written
* to persistent storage.
*/
boolean commit();

1,commit方法是有一个boolean的返回值
2,当数据变化进行存储时是一个原子性的操作
3,当两个editor对象同时对一个共享的preferences参数进行操作时,永远都是最后一个调用commit方法的editor变更了最后的数据值


/**
* Commit your preferences changes back from this Editor to the
* {@link SharedPreferences} object it is editing.  This atomically
* performs the requested modifications, replacing whatever is currently
* in the SharedPreferences.
*
* <p>Note that when two editors are modifying preferences at the same
* time, the last one to call apply wins.
*
* <p>Unlike {@link #commit}, which writes its preferences out
* to persistent storage synchronously, {@link #apply}
* commits its changes to the in-memory
* {@link SharedPreferences} immediately but starts an
* asynchronous commit to disk and you won't be notified of
* any failures.  If another editor on this
* {@link SharedPreferences} does a regular {@link #commit}
* while a {@link #apply} is still outstanding, the
* {@link #commit} will block until all async commits are
* completed as well as the commit itself.
*
* <p>As {@link SharedPreferences} instances are singletons within
* a process, it's safe to replace any instance of {@link #commit} with
* {@link #apply} if you were already ignoring the return value.
*
* <p>You don't need to worry about Android component
* lifecycles and their interaction with <code>apply()</code>
* writing to disk.  The framework makes sure in-flight disk
* writes from <code>apply()</code> complete before switching
* states.
*
* <p class='note'>The SharedPreferences.Editor interface
* isn't expected to be implemented directly.  However, if you
* previously did implement it and are now getting errors
* about missing <code>apply()</code>, you can simply call
* {@link #commit} from <code>apply()</code>.
*/
void apply();

1,apply方法是没有返回值的
2,当两个editor同时对preferences对象编辑时,也是最后一个调用apply方法的对象编辑数据
3,apply的提交操作也是原子性的

以上是我直接参考了这篇博客的结论:https://www.jianshu.com/p/c8d10357c939

其实我们Android studio的很强大,当你使用editor.commit();的时候直接推荐你使用apply,commit直接写入持久化内存,apply在后台处理它

Consider using apply() instead; commit writes its data to persistent storage immediately, whereas apply will handle it in the background

他们的区别总结:
apply()没有返回值,commit()有返回值,在不关心结果的时候推荐使用apply()
commit()直接写入持久化内存,是同步过程,速度比apply()慢,apply()是异步的提交,速度更快

存取数据使用多张表还是一张表

我们知道SharedPreferences存储的格式是xml,既然是xml就要用到解析,只不过这个解析过程我们是看不到的也不需要去关心,但是解析的速度却会影响到我们的用户体验,加入一张表里面有很多数据,比如你把一个页面的数据存起来了,数据量比较大,那么这个时候推荐为这些数据单独建立一个表,也就是推荐不同的数据放不同的表里面,防止所有数据都放在一张表里面一次读取要耗费很长时间

参考链接:
https://www.jianshu.com/p/c8d10357c939

相关标签: SharedPreferences