作为 Android 的数据存储方式之一的 SharedPreferences(以下简称SP),我们在开发中也是或多或少会用到。今天就来总结一下如何使用 SP 以及使用 SP 的注意事项。

1.首先先聊聊使用 SP 的注意事项

  • SP 适合存储一些轻量级的持久化数据,如果你的数据量很大,那么建议你更换存储方式。
  • SP 提供了数据的一致性,但这是以牺牲程序性能为代价的,所以如果存储的数据需要经常修改,那么建议你更换存储方式。
  • SP 是不支持多进程读写的,如果你需要多进程对数据进行读写访问,那么建议你更换存储方式。
  • SP 的 commit 方法是同步进行的,apply 是异步进行的,两者都是以替换上次数据来进行数据更新的,如果同时有两个地方调用 commit 或者 apply ,以最后一次调用为最终数据更新。
  • 如果你不关心 SP 的操作返回值,同时你还是在 Android 主线程进行操作,那么建议你使用 apply 方法进行数据更新。
  • 因为 SP 的 apply 方法会异步进行数据更新,那么在 apply 方法尚未完成的时候,调用 commit 方法进行数据更新,就会使 commit 方法进行阻塞,直到 apply 方法完成所有的异步数据更新。

2. 好的,接下来我们就来看看 SP 的具体使用

  • SP 使应用程序共享它的同一个实例,通过 XML 以 key-value 的形式保存数据。
  • SP 主要用来保存一些轻量级的数据(字符串、基本数据类型),比如应用程序的各种配置信息,以及一些简单的账号、密码等。
  • SP 的数据文件储存位置:data/data/应用程序包名/shared_prefs/
  • SP 的数据访问模式
MODE_PRIVATR 默认模式,创建保存的文件只能本应用程序或者拥有相同用户ID的应用程序访问
MODE_WORLD_READABLE 允许所有应用程序对创建的文件进行读操作权限(官方不建议使用,数据不安全)
MODE_WORLD_WRITEABLE 允许所有应用程序对创建的文件进行写操作权限(官方不建议使用,数据不安全)
  • SP的方法
adstract  boolean

contains(String key)

检查SP文件是否包含此 key。

adstract  SharedPreferences.Editor

edit()

创建一个SP文件编辑器,通过这个编辑器可以编辑SP里面的内容,并将这些修改提交给SP。

adstract Map

getAll()

从SP中查询出所有的 key-value。

adstract  boolean

getBoolean(String key,boolean defValue)

根据 key 从 SP 中查询对应的 boolean 值,如果查不到就返回默认值。

adstract  float

getFloat(String key,float defValue)

根据 key 从 SP 中查询对应的 float 值,如果查不到就返回默认值。

adstract  int

getInt(String key,int defValue)

根据 key 从 SP 中查询对应的 int 值,如果查不到就返回默认值。

adstract  long

getLong(String key,long defValue)

根据 key 从 SP 中查询对应的 long 值,如果查不到就返回默认值。

adstract  String

getString(String key,String defValue)

根据 key 从 SP 中查询对应的 String 值,如果查不到就返回默认值。

adstract  Set

getStringSet(String key,Set defValue)

根据 key 从 SP 中查询对应的一组 String 值,如果查不到就返回默认值。

adstract  void

registerOnSharedPreferencesChangeListener(SharedPreferences.OnSharedPreferencesChangeListener

  listener )

注册SP发生改变的监听回调

adstract  void

unregisterOnSharedPreferencesChangeListener(SharedPreferences.OnSharedPreferencesChangeListener

  listener )

取消SP发生改变的监听回调

  • SharedPreferences.Editor 接口的方法
adstract  void

apply()

将SP的修改返回给当前正在被编辑的SP。(异步提交,不保证数据完整性,如果你在apply() 未完成前调用commit(),则会造成commit()阻塞,直到apply()执行完成,才会执行commit(),如果你不在乎返回值的话,可以将 commit() 替换成 apply()。)

adstract  SharedPreferences.Editor

clear()

清空SP中的所有数据。

adstract  boolean

commit()

将SP的修改返回给当前正在被编辑的SP。(同步提交)

如果您不关心返回值并且正在从应用程序的主线程中使用它,请考虑使用apply()。

adstract  SharedPreferences.Editor

PutBoolean(String key,boolean value)

在SP编辑器中设置一个布尔值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutFloat(String key,float value)

在SP编辑器中设置一个float值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutInt(String key,int value)

在SP编辑器中设置一个int值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutLong(String key,long value)

在SP编辑器中设置一个long值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutString(String key,String value)

在SP编辑器中设置一个String值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutStringSet(String key,Set value)

在SP编辑器中设置一组String值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

remove(String key)

根据key,删除SP中的值。

至此SP的功能已经介绍完了。

我们接下来就看看具体的用法以及自己实现一个SPUtils。

  • 我们先动手封装一个SPUtils,这样大大减少了很多的模板代码,你也可以根据自己的业务自定义封装,以下是我封装的。
import android.content.Context;import android.content.SharedPreferences;import java.util.Map;public class SPUtils {    private final static String spName = "Test";    public static void putValue(Context context, String key, Object value) {        SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);        SharedPreferences.Editor edit = sp.edit();        if (value instanceof Boolean) {            edit.putBoolean(key, (Boolean) value);        } else if (value instanceof Float) {            edit.putFloat(key, (Float) value);        } else if (value instanceof Integer) {            edit.putInt(key, (Integer) value);        } else if (value instanceof Long) {            edit.putLong(key, (Long) value);        } else if (value instanceof String) {            edit.putString(key, (String) value);        }        edit.apply();    }    public static Object getValue(Context context, String key, Object defValue) {        SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);        if (defValue instanceof Boolean) {            return sp.getBoolean(key, (Boolean) defValue);        } else if (defValue instanceof Float) {            return sp.getFloat(key, (Float) defValue);        } else if (defValue instanceof Integer) {            return sp.getInt(key, (Integer) defValue);        } else if (defValue instanceof Long) {            return sp.getLong(key, (Long) defValue);        } else if (defValue instanceof String) {            return sp.getString(key, (String) defValue);        }        return null;    }    public static void clearSP(Context context) {        context.getSharedPreferences(spName, Context.MODE_PRIVATE)                .edit()                .clear()                .apply();    }    public static void removeSP(Context context, String Key) {        context.getSharedPreferences(spName, Context.MODE_PRIVATE)                .edit()                .remove(Key)                .apply();    }        public static Map getAllSP(Context context) {        return context.getSharedPreferences(spName, Context.MODE_PRIVATE).getAll();    }}
  • 我们现在模拟登录页面保存账号密码的功能。我创建了两个button,一个用来存储账号密码,一个用来读取账号密码并且进行删除和清空操作。具体如下:
public class MainActivity extends AppCompatActivity {    public static final String SP_USERNAME_KEY = "SP_USERNAME_KEY";    public static final String SP_PASSWORD_KEY = "SP_PASSWORD_KEY";    public static final String TAG = "Main_Activity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.btn_put).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                SPUtils.putValue(MainActivity.this, SP_USERNAME_KEY, "哈哈");                SPUtils.putValue(MainActivity.this, SP_PASSWORD_KEY, 123456);            }        });        findViewById(R.id.btn_get).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //1.首次正常获取                Map allSP = SPUtils.getAllSP(MainActivity.this);                int size = allSP.size();                Log.d(TAG, "1.getAllSP.size() --> " + size);                String username = (String) SPUtils.getValue(MainActivity.this, SP_USERNAME_KEY, "");                int password = (int) SPUtils.getValue(MainActivity.this, SP_PASSWORD_KEY, -1);                Log.d(TAG, "1.username --> " + username + " ,1.password --> " + password);                //2.删除 SP_USERNAME_KEY 后,打印sp数量,以及数据情况                SPUtils.removeSP(MainActivity.this, SP_USERNAME_KEY);                Map allSP2 = SPUtils.getAllSP(MainActivity.this);                int size2 = allSP2.size();                Log.d(TAG, "2.getAllSP.size() --> " + size2);                String username2 = (String) SPUtils.getValue(MainActivity.this, SP_USERNAME_KEY, "");                int password2 = (int) SPUtils.getValue(MainActivity.this, SP_PASSWORD_KEY, -1);                Log.d(TAG, "2.username --> " + username2 + " ,2.password --> " + password2);                //清空sp后,打印sp数量,以及数据情况                SPUtils.clearSP(MainActivity.this);                Map allSP3 = SPUtils.getAllSP(MainActivity.this);                int size3 = allSP3.size();                Log.d(TAG, "3.getAllSP.size() --> " + size3);                String username3 = (String) SPUtils.getValue(MainActivity.this, SP_USERNAME_KEY, "");                int password3 = (int) SPUtils.getValue(MainActivity.this, SP_PASSWORD_KEY, -1);                Log.d(TAG, "3.username --> " + username3 + " ,3.password --> " + password3);            }        });    }}
  • 此为Log输出信息:
D/Main_Activity: 1.getAllSP.size() --> 2D/Main_Activity: 1.username --> 哈哈 ,1.password --> 123456D/Main_Activity: 2.getAllSP.size() --> 1D/Main_Activity: 2.username -->  ,2.password --> 123456D/Main_Activity: 3.getAllSP.size() --> 0D/Main_Activity: 3.username -->  ,3.password --> -1

至此SP的介绍以及使用就完毕了,希望对你有帮助。

欢迎加入Q群一起探讨Android问题。

 

更多相关文章

  1. Android(安卓)APP连接电脑数据库(以SQL Server为例)
  2. 9个非常棒的Android代码编辑器 移动开发者的最爱
  3. Android(安卓)Studio Jni开发(二)实现Native调用java方法和Native
  4. android SQLite数据库1
  5. 初学android-调用百度api显示地图(出现显示网格问题)
  6. Android(安卓)小型社交软件客户端开发技术栈+案例
  7. Android音频系统之AudioTrack起播线与underrun问题研究(Android(
  8. Android(安卓)RecyclerView中ViewHolder的复用导致数据错乱解决
  9. Android数据传输加密(一):Base64转码算法

随机推荐

  1. 农民伯伯的2013
  2. 【Android】数据存储之Network
  3. Android(安卓)蓝牙开发基本流程
  4. Android Studio中同步代码时报:Received s
  5. android 中文api (84) ―― TrafficStats
  6. GreeDAO详解-----数据库升级详解
  7. Retrofit简要介绍
  8. Android(安卓)StickyLayout与触摸事件详
  9. Android(安卓)Bluetooth蓝牙开发:Bluetoot
  10. 我对Android(安卓)Activity的生命周期是