热门标签 | 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;
}
}

推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 本文介绍如何利用动态规划算法解决经典的0-1背包问题。通过具体实例和代码实现,详细解释了在给定容量的背包中选择若干物品以最大化总价值的过程。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • MQTT技术周报:硬件连接与协议解析
    本周开发笔记重点介绍了在新项目中使用MQTT协议进行硬件连接的技术细节,涵盖其特性、原理及实现步骤。 ... [详细]
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社区 版权所有