Question: 1
SharedPreferences有没有现成安全机制 ???
如果有,如何做,通用做法??? 还是内部支持 ???
Question: 2
SharedPreferences在读写的操作上有什么优化建议、优化空间 ???
一个轻量级的存储类,特别适合用于保存软件配置参数。
(是用
xml
文件存放数据,文件存放在/data/data//shared_prefs目录下)
有时候需要将少量简单类型数据保存在本地,例如用户的配置数据、用户的部分非强安全数据(如用户名、用户的头像等等)
有时候,也可以通过利用SharedPreferences来存储用户的用户名和密码,以此来达到用户打开APP时同步登录、记住密码一键登录的需求/效果。
这些需求存储的数据一般都比较简单
SharedPreferences可以保存的数据类型有:int、boolean、float、long、String、StringSet。
tips:对于Java或kotlin的对象类型数据(例如用来存储用户名、密码等用户信息的User类),则可以将其进行序列化为字符串进行存储
保存数据一般分为四个步骤:
getSharedPreferences
方法获得SharedPreferences对象;edit
获得SharedPreferences.Editor对象;putXXX
方法写入key-value对;commit
方法保存key-value对。读取数据一般分为两个步骤:
getSharedPreferences
方法获得SharedPreferences对象;getXXX
方法获取数据;public abstract SharedPreferences getSharedPreferences (String name, int mode)
作用:用于获取SharedPreferences对象
(根据name查找SharedPreferences,若已经存在则获取,若不存在则创建一个新的)
参数
name:命名
mode:模式,包括
MODE_PRIVATE(只能被自己的应用程序访问)
MODE_WORLD_READABLE(除了自己访问外还可以被其它应该程序读取)
MODE_WORLD_WRITEABLE(除了自己访问外还可以被其它应该程序读取和写入)
值得关注的是,若该Activity只需要创建一个SharedPreferences对象的时候,可以使用getPreferences
方法,不需要为SharedPreferences对象命名,只要传入参数mode即可
public SharedPreferences getPreferences (int mode)
abstract SharedPreferences.Editor edit()
作用:用于获取SharedPreferences的Editor对象
3.3 putXxx()
//写入boolean类型的数据
abstract SharedPreferences.Editor putBoolean(String key, boolean value)
//写入float类型的数据
abstract SharedPreferences.Editor putFloat(String key, float value)
//写入int类型的数据
abstract SharedPreferences.Editor putInt(String key, int value)
//写入long类型的数据
abstract SharedPreferences.Editor putLong(String key, long value)
//写入String类型的数据
abstract SharedPreferences.Editor putString(String key, String value)
//写入Set类型的数据
abstract SharedPreferences.Editor putStringSet(String key, Set<String> values)
作用:用于完成数据的写入
注意,是通过SharedPreferences的Editor对象完成调用
参数
key:指定数据对应的key
value:指定的值
作用:用于移除指定key的数据
abstract SharedPreferences.Editor remove(String key)
参数
key:指定数据的key
(TODO: Key不存在时的处理方法是怎么样的)
作用:清空数据(谨慎操作)
3.7 getXxx() 读取数据
//读取所有数据
abstract Map<String, ?> getAll()
//读取的数据为boolean类型
abstract boolean getBoolean(String key, boolean defValue)
//读取的数据为float类型
abstract float getFloat(String key, float defValue)
//读取的数据为int类型
abstract int getInt(String key, int defValue)
//读取的数据为long类型
abstract long getLong(String key, long defValue)
//读取的数据为String类型
abstract String getString(String key, String defValue)
//读取的数据为Set类型
abstract Set<String> getStringSet(String key, Set<String> defValues)
参数
key:指定数据的key
defValue:当读取不到指定的数据时,使用的默认值defValue
/**
* 保存用户信息
*/
private void saveUserInfo(){
SharedPreferences userInfo = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = userInfo.edit();//获取Editor
//得到Editor后,写入需要保存的数据
editor.putString("username", "一只猫的涵养");
editor.putInt("age", 20);
editor.commit();//提交修改
Log.i(TAG, "保存用户信息成功");
}
/**
* 读取用户信息
*/
private void getUserInfo(){
SharedPreferences userInfo = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
String username = userInfo.getString("username", null);//读取username
int age = userInfo.getInt("age", 0);//读取age
Log.i(TAG, "读取用户信息");
Log.i(TAG, "username:" + username + ", age:" + age);
}
/**
* 移除年龄信数据
*/
private void removeUserInfo(){
SharedPreferences userInfo = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = userInfo.edit();//获取Editor
editor.remove("age");
editor.commit();
Log.i(TAG, "移除年龄数据");
}
/**
* 清空数据
*/
private void clearUserInfo(){
SharedPreferences userInfo = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = userInfo.edit();//获取Editor
editor.clear();
editor.commit();
Log.i(TAG, "清空数据");
}
SharedPreferences被编辑时的监听
SharedPreferences.OnSharedPreferenceChangeListener changeListener = new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
//preferences被 编辑的SharedPreferences实例
//该SharedPreferences中被编辑的条目所对应的key
}
};
//userInfo注册监听事件
userInfo.registerOnSharedPreferenceChangeListener(changeListener);
//userInfo注销监听事件
userInfo.unregisterOnSharedPreferenceChangeListener(changeListener);
ShredPreferences是单例对象,第一次打开后,之后获取都无需创建,速度很快。
当第一次获取数据后,数据会被加载到一个缓存的Map中,之后的读取都会非常快。
当由于是 XML <—> Map 的存储方式,所以,数据越大,操作越慢,get、commit、apply、remove、clear都会受影响,所以尽量把数据按功能拆分成若干份(即对应3.1中的api,传入name进行区分)。
Question:
这些方法、常量在Activity中可以直接调用
getSharedPreferences (String name, int mode)
getPreferences (int mode)
MODE_PRIVATE
而如果不是在Activity中,例如是在Service或者其他工具类中,则是通过Context对象来进行获取:
context.getSharedPreferences (String name, int mode)
context.getPreferences (int mode)
Conetxt.MODE_PRIVATE
保存的SharedPreferences数据将一直存在,除非被覆盖、移除、清空或文件被删除。
SharedPreferences保存的数据会随着应用的卸载而被删除
注意,覆盖安装(例如版本更新)并不会删除或清空SharedPreferences文件
(这里的强类型是个人定义.)
即,在SharedPreferences中存储的value不限定类型,与最新一次的覆盖写入有关
例如,如下两个代码都会造成key为age的数据被覆盖写入而发生更新变化
case 1:
editor.putInt("age", 20);
//覆盖key为age的数据,得到的结果:age = 32
editor.putInt("age", 32);
// 这时候通过
sharedPreferences.getInt("age", 0) // 获取得到的值为:
case 2:
editor.putString("age", "20");
//覆盖key为age的数据,得到的结果:age = 32 (int类型)
editor.putInt("age", 32);
// 这时候通过
sharedPreferences.getInt("age", 0) // 获取得到的值为:
sharedPreferences.getString("age", "0") // 获取得到的值为:
所读取的key存在,但是读取时指定的类型不对应,则会产生运行时异常。
editor.putInt("age", 32);//保存为int类型
String age = userInfo.getString("age", "null");//读取时为String类型,出现异常
// putXxx()
editor.putInt("age", 20);//写入操作
editor.remove("age"); //移除操作
editor.clear(); //清空操作
editor.commit();//记得commit