热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【android学习】SharedPreferences详解

1,概念SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些常用配置,以XML文件的形式存储的键值对(key-value)数据的数据存储方
1,概念

SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些常用配置,以XML文件的形式存储的键值对(key-value)数据的数据存储方式保存在 /data/data/PACKAGE_NAME/shared_prefs目录下。

2,场景

一般用于储存应用的配置等信息。
注意:SharedPreferences文件并不安全,手机root后即可查看其信息,请勿存储用户信息、密码等敏感信息。(可以不存放密码,存放用户名,登录时检测有用户名则直接登录,可限定日期)

1)少量数据的保存
2)数据格式简单(基本数据类型)
如配置信息(是否打开音效、是否使用震动效果)、游戏的积分信息。
如各个界面需要相互传递的信息(用户名、用户头像修改、传值过于麻烦,直接存储在SharedPreferences中)
3)通过key-value的方式保存数据

3,实现

1)SharePreferences对象

通过Context上下文获取。

SharedPreferences preferences=getSharedPreferences("user",Context.MODE_PRIVATE);
--Use 0 or MODE_PRIVATE 默认设置,只能被本应用读写 --MODE_WORLD_READABLE 被其他应用程序读,不可写 --MODE_WORLD_WRITEABLE 被其他应用程序读写

2)Editor对象

调用SharePreferences的edit()方法返回一个Editor对象。
abstract SharedPreferences.Editor edit()

Editor editor=preferences.edit();

3)设置数据

通过Editor的putXXX(key , value)方法。

String name="xixi";
String age="22";
editor.putString("name", name);
editor.putString("age", age);

4)关闭对象

通过Editor的 commit(); 方法。

editor.commit();//返回boolean

5)其他

contains(String key) 判定SharedPreference是否包含key对应的值
Map<String, ?> getAll() 获取SharePreference里面全部的数据对
SharedPreferences.Editor remove(String key) 移除
SharedPreferences.Editor clear() 清除所有的数据
4,优缺点

1)优点

①可以全局共享访问
②对于常规的轻量级而言比SQLite好一点。
当存储量不大的时候可以考虑自己定义文件格式。

2)缺点

①保存为xml文件,整体效率来看不是特别的高,但却高于SQLit

xml处理时Dalvik会通过自带底层的本地XML Parser解析,比如XMLpull方式,这样对于内存资源占用比较好。

②安全性较差,请勿保存敏感信息

③对于较大的存储文件,会造成界面卡顿

SharedPreference在创建时会把整个文件全部加载进内存,如果文件较大,会出现以下问题:
i>第一次从sp中获取值的时候,有可能阻塞主线程,使界面卡顿、掉帧。
ii>解析sp的时候会产生大量的临时对象,导致频繁GC,引起界面卡顿。
iii>这些key和value会永远存在于内存之中,占用大量内存。

5,安全性

1)开发者在创建文件时务必选取合适的创建模式(MODE_PRIVATE、MODE_WORLD_READABLE以及MODE_WORLD_WRITEABLE)进行权限控制。
2)避免使用MODE_WORLD_WRITEABLE和MODE_WORLD_READABLE模式创建进程间通信的文件,此处即为Shared Preferences;如果需要与其他进程应用进行数据共享,请考虑使用content provider。
3)不要在使用“android:sharedUserId”属性的同时,对应用使用测试签名,否则其他应用拥有“android:sharedUserId”属性值和测试签名时,将会访问到内部存储文件数据。

6,优化

1)不要存放大的key和value,会引起界面卡、频繁GC、占用内存等等。
2)毫不相关的配置项就不要放在在一起,文件越大读取越慢。
3)读取频繁的key和不易变动的key尽量不要放在一起,影响速度,如果整个文件很小,那么忽略吧,为了这点性能添加维护成本得不偿失。
4)不要乱edit和apply,尽量批量修改一次提交,多次apply会阻塞主线程。
5)尽量不要存放JSON和HTML,这种场景请直接使用JSON。
6)SharedPreference无法进行跨进程通信,MODE_MULTI_PROCESS只是保证了在API 11以前的系统上,如果sp已经被读取进内存,再次获取这个SharedPreference的时候,如果有这个flag,会重新读一遍文件,仅此而已。

7,demo

1)简单用法

//FILE_BD 保存账户绑定信息
SharedPreferences preferences_BD = null;
String FILE_BD = "saveUserBind";//用于保存账户绑定信息
...
//读入信息
void PutScopeClose(){
if (preferences_BD == null) {
preferences_BD = mContext.getSharedPreferences(FILE_BD, MODE_PRIVATE);
}
Editor editPhOne= preferences_BD.edit();
switch (arr[1]) {
case "onebind":
editPhone.putString("Scope_Close1", arr[2]);
break;
case "twobind":
editPhone.putString("Scope_Close2", arr[2]);
break;
}
editPhone.commit();
}
//获取开启关闭安全距离信息
String GetScopeClose(){
String sendStr="";
preferences_BD = mContext.getSharedPreferences(FILE_BD, MODE_PRIVATE);
sendStr = preferences_BD.getString("Scope_Close1", "close") + "," +
preferences_BD.getString("Scope_Close2", "close") + "," + ":end" + ",";
return sendStr;
}

2)封装SharePreferenceUtil

public class SharePreferenceUtil {
public static boolean isLogin(SharedPreferences sp){
return sp.getBoolean("isLogin", false);
}
public static SharedPreferences getSharePerference(Context context){
return context.getSharedPreferences(VariableUtil.APPLICATION_NAME, Context.MODE_PRIVATE);
}
public static void setStringSharedPerference(SharedPreferences sp,String key,String value){
Editor editor=sp.edit();
editor.putString(key, value);
editor.commit();
}
public static void setStrsSharedPerference(SharedPreferences sp,String[] key,String[] value){
Editor editor=sp.edit();
for(int i=0;i editor.putString(key[i], value[i]);
LogUtils.i(tag, " setStrsSharedPerference: " + key[i] + "," + value[i]);
}
editor.commit();
}
public static void removeStrsSharedPerference(SharedPreferences sp,String[] key){
Editor editor=sp.edit();
for(int i=0;i editor.remove(key[i]);
LogUtils.i(tag, " removeStrsSharedPerference: " + key[i]);
}
editor.commit();
}
public static void setBooleanSharedPerference(SharedPreferences sp,String key,boolean value){
Editor editor=sp.edit();
editor.putBoolean(key, value);
editor.commit();
}
/** * 删除缓存中的图片数据 */
public static void removeTempFromPref(Context context,String key) {
SharedPreferences sp = context.getSharedPreferences(VariableUtil.APPLICATION_NAME, 0);
sp.edit().remove(key).commit();
}
}

3)封装SPUtils

SPUtils spUtils1 = SPUtils.getInstance(Config.USER_INFO);
spUtils1.put(Config.USER_ID, id);//Config为常量bean

import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
public class SPUtils {
private static Map sSPMap = new HashMap<>();
private SharedPreferences sp;
/** * 获取SP实例 * * @return {@link SPUtils} */
public static SPUtils getInstance() {
return getInstance("");
}
/** * 获取SP实例 * * @param spName sp名 * @return {@link SPUtils} */
public static SPUtils getInstance(String spName) {
if (isSpace(spName)) spName = "spUtils";
SPUtils sp = sSPMap.get(spName);
if (sp == null) {
sp = new SPUtils(spName);
sSPMap.put(spName, sp);
}
return sp;
}
private SPUtils(String spName) {
sp = MyApplication.context.getSharedPreferences(spName, Context.MODE_PRIVATE);
}
/** * SP中写入String * * @param key 键 * @param value 值 */
public void put(@NonNull String key, @NonNull String value) {
sp.edit().putString(key, value).apply();
}
/** * SP中读取String * * @param key 键 * @return 存在返回对应值,不存在返回默认值{@code null} */
public String getString(@NonNull String key) {
return getString(key, "");
}
/** * SP中读取String * * @param key 键 * @param defaultValue 默认值 * @return 存在返回对应值,不存在返回默认值{@code defaultValue} */
public String getString(@NonNull String key, @NonNull String defaultValue) {
return sp.getString(key, defaultValue);
}
/** * SP中写入int * * @param key 键 * @param value 值 */
public void put(@NonNull String key, int value) {
sp.edit().putInt(key, value).apply();
}
/** * SP中读取int * * @param key 键 * @return 存在返回对应值,不存在返回默认值-1 */
public int getInt(@NonNull String key) {
return getInt(key, -1);
}
/** * SP中读取int * * @param key 键 * @param defaultValue 默认值 * @return 存在返回对应值,不存在返回默认值{@code defaultValue} */
public int getInt(@NonNull String key, int defaultValue) {
return sp.getInt(key, defaultValue);
}
/** * SP中写入long * * @param key 键 * @param value 值 */
public void put(@NonNull String key, long value) {
sp.edit().putLong(key, value).apply();
}
/** * SP中读取long * * @param key 键 * @return 存在返回对应值,不存在返回默认值-1 */
public long getLong(@NonNull String key) {
return getLong(key, -1L);
}
/** * SP中读取long * * @param key 键 * @param defaultValue 默认值 * @return 存在返回对应值,不存在返回默认值{@code defaultValue} */
public long getLong(@NonNull String key, long defaultValue) {
return sp.getLong(key, defaultValue);
}
/** * SP中写入float * * @param key 键 * @param value 值 */
public void put(@NonNull String key, float value) {
sp.edit().putFloat(key, value).apply();
}
/** * SP中读取float * * @param key 键 * @return 存在返回对应值,不存在返回默认值-1 */
public float getFloat(@NonNull String key) {
return getFloat(key, -1f);
}
/** * SP中读取float * * @param key 键 * @param defaultValue 默认值 * @return 存在返回对应值,不存在返回默认值{@code defaultValue} */
public float getFloat(@NonNull String key, float defaultValue) {
return sp.getFloat(key, defaultValue);
}
/** * SP中写入boolean * * @param key 键 * @param value 值 */
public void put(@NonNull String key, boolean value) {
sp.edit().putBoolean(key, value).apply();
}
/** * SP中读取boolean * * @param key 键 * @return 存在返回对应值,不存在返回默认值{@code false} */
public boolean getBoolean(@NonNull String key) {
return getBoolean(key, false);
}
/** * SP中读取boolean * * @param key 键 * @param defaultValue 默认值 * @return 存在返回对应值,不存在返回默认值{@code defaultValue} */
public boolean getBoolean(@NonNull String key, boolean defaultValue) {
return sp.getBoolean(key, defaultValue);
}
/** * SP中写入String集合 * * @param key 键 * @param values 值 */
public void put(@NonNull String key, @NonNull Set values) {
sp.edit().putStringSet(key, values).apply();
}
/** * SP中读取StringSet * * @param key 键 * @return 存在返回对应值,不存在返回默认值{@code null} */
public Set getStringSet(@NonNull String key) {
return getStringSet(key, Collections.emptySet());
}
/** * SP中读取StringSet * * @param key 键 * @param defaultValue 默认值 * @return 存在返回对应值,不存在返回默认值{@code defaultValue} */
public Set getStringSet(@NonNull String key, @NonNull Set defaultValue) {
return sp.getStringSet(key, defaultValue);
}
/** * SP中获取所有键值对 * * @return Map对象 */
public Map getAll() {
return sp.getAll();
}
/** * SP中移除该key * * @param key 键 */
public void remove(@NonNull String key) {
sp.edit().remove(key).apply();
}
/** * SP中是否存在该key * * @param key 键 * @return {@code true}: 存在
{@code false}: 不存在 */

public boolean contains(@NonNull String key) {
return sp.contains(key);
}
/** * SP中清除所有数据 */
public void clear() {
sp.edit().clear().apply();
}
private static boolean isSpace(String s) {
if (s == null) return true;
for (int i = 0, len = s.length(); i if (!Character.isWhitespace(s.charAt(i))) {
return false;
}
}
return true;
}
}

推荐阅读
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
author-avatar
GXtingker
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有