数据存储:SharedPreferences(SP)"/>
Android 数据存储:SharedPreferences(SP)
作为 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<String,?> | 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<String> | getStringSet(String key,Set<String> 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<String> 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<String, ?> 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";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.btn_put).setOnClickListener(new View.OnClickListener() {@Overridepublic 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() {@Overridepublic void onClick(View v) {//1.首次正常获取Map<String, ?> 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<String, ?> 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<String, ?> 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() --> 2
D/Main_Activity: 1.username --> 哈哈 ,1.password --> 123456
D/Main_Activity: 2.getAllSP.size() --> 1
D/Main_Activity: 2.username --> ,2.password --> 123456
D/Main_Activity: 3.getAllSP.size() --> 0
D/Main_Activity: 3.username --> ,3.password --> -1
至此SP的介绍以及使用就完毕了,希望对你有帮助。
欢迎加入Q群一起探讨Android问题。
更多推荐
Android 数据存储:SharedPreferences(SP)
发布评论